Regina 7.4 Calculation Engine
regina::Triangulation< 3 > Class Reference

Represents a 3-dimensional triangulation, typically of a 3-manifold. More...

#include <triangulation/dim3.h>

Inheritance diagram for regina::Triangulation< 3 >:
regina::detail::TriangulationBase< 3 > regina::Snapshottable< Triangulation< dim > > regina::PacketData< Triangulation< dim > > regina::Output< Triangulation< dim > > regina::TightEncodable< Triangulation< dim > > regina::TopologyLockable regina::SnapPeaTriangulation

Public Types

using TuraevViroSet
 A map from (r, parity) pairs to Turaev-Viro invariants, as described by turaevViro().
 
using PacketChangeGroup
 A type alias for PacketChangeSpan, used when a span is being used purely for optimisation purposes.
 

Public Member Functions

bool isReadOnlySnapshot () const
 Determines if this object is a read-only deep copy that was created by a snapshot.
 
std::shared_ptr< PacketOf< Triangulation< dim > > > packet ()
 Returns the packet that holds this data, if there is one.
 
std::shared_ptr< const PacketOf< Triangulation< dim > > > packet () const
 Returns the packet that holds this data, if there is one.
 
std::string anonID () const
 A unique string ID that can be used in place of a packet ID.
 
std::string str () const
 Returns a short text representation of this object.
 
std::string utf8 () const
 Returns a short text representation of this object using unicode characters.
 
std::string detail () const
 Returns a detailed text representation of this object.
 
std::string tightEncoding () const
 Returns the tight encoding of this object.
 
size_t hash () const
 Hashes this object to a non-negative integer, allowing it to be used for keys in hash tables.
 
Constructors and Destructors
 Triangulation ()=default
 Default constructor.
 
 Triangulation (const Triangulation &src)
 Creates a new copy of the given triangulation.
 
 Triangulation (const Triangulation &src, bool cloneProps, bool cloneLocks=true)
 Creates a new copy of the given triangulation, with the option of whether or not to clone its computed properties and/or locks also.
 
 Triangulation (Triangulation &&src) noexcept=default
 Moves the given triangulation into this new triangulation.
 
 Triangulation (const Link &link, bool simplify=true)
 Deprecated constructor that creates a new ideal triangulation representing the complement of the given link diagram.
 
 Triangulation (const std::string &description)
 "Magic" constructor that tries to find some way to interpret the given string as a triangulation.
 
 Triangulation (snappy::Manifold m)
 Python-only constructor that copies the given SnapPy manifold.
 
 ~Triangulation ()
 Destroys this triangulation.
 
std::shared_ptr< PacketinAnyPacket ()
 Returns the packet that holds this data, even if it is held indirectly via a SnapPea triangulation.
 
std::shared_ptr< const PacketinAnyPacket () const
 Returns the packet that holds this data, even if it is held indirectly via a SnapPea triangulation.
 
SnapPeaTriangulationisSnapPea ()
 Returns the SnapPea triangulation that holds this data, if there is one.
 
const SnapPeaTriangulationisSnapPea () const
 Returns the SnapPea triangulation that holds this data, if there is one.
 
Tetrahedra
Tetrahedron< 3 > * newTetrahedron ()
 A dimension-specific alias for newSimplex().
 
Tetrahedron< 3 > * newTetrahedron (const std::string &desc)
 A dimension-specific alias for newSimplex().
 
template<int k>
std::array< Tetrahedron< 3 > *, k > newTetrahedra ()
 A dimension-specific alias for newSimplices().
 
void newTetrahedra (size_t k)
 A dimension-specific alias for newSimplices().
 
void removeTetrahedron (Tetrahedron< 3 > *tet)
 A dimension-specific alias for removeSimplex().
 
void removeTetrahedronAt (size_t index)
 A dimension-specific alias for removeSimplexAt().
 
void removeAllTetrahedra ()
 A dimension-specific alias for removeAllSimplices().
 
Triangulationoperator= (const Triangulation &src)
 Sets this to be a (deep) copy of the given triangulation.
 
Triangulationoperator= (Triangulation &&src)
 Moves the contents of the given triangulation into this triangulation.
 
void swap (Triangulation< 3 > &other)
 Swaps the contents of this and the given triangulation.
 
Skeletal Queries
bool hasBoundaryTriangles () const
 A dimension-specific alias for hasBoundaryFacets().
 
size_t countBoundaryTriangles () const
 A dimension-specific alias for countBoundaryFacets().
 
bool hasTwoSphereBoundaryComponents () const
 Determines if this triangulation contains any two-sphere boundary components.
 
bool hasNegativeIdealBoundaryComponents () const
 Determines if this triangulation contains any ideal boundary components with negative Euler characteristic.
 
bool hasMinimalBoundary () const
 Determines whether the boundary of this triangulation contains the smallest possible number of triangles.
 
bool hasMinimalVertices () const
 Determines whether this triangulation contains the smallest possible number of vertices for the 3-manifold that it represents.
 
Basic Properties
long eulerCharManifold () const
 Returns the Euler characteristic of the corresponding compact 3-manifold.
 
bool isIdeal () const
 Determines if this triangulation is ideal.
 
bool isStandard () const
 Determines if this triangulation is standard.
 
bool isClosed () const
 Determines if this triangulation is closed.
 
bool isOrdered () const
 Determines if this triangulation is ordered; that is, if tetrahedron vertices are labelled so that all gluing permutations are order-preserving on the tetrahedron faces.
 
Algebraic Properties
const AbelianGrouphomologyRel () const
 Returns the relative first homology group with respect to the boundary for this triangulation.
 
const AbelianGrouphomologyBdry () const
 Returns the first homology group of the boundary for this triangulation.
 
unsigned long homologyH2Z2 () const
 Returns the second homology group with coefficients in Z_2 for this triangulation.
 
Cyclotomic turaevViro (unsigned long r, bool parity=true, Algorithm alg=Algorithm::Default, ProgressTracker *tracker=nullptr) const
 Computes the given Turaev-Viro state sum invariant of this 3-manifold using exact arithmetic.
 
double turaevViroApprox (unsigned long r, unsigned long whichRoot=1, Algorithm alg=Algorithm::Default) const
 Computes the given Turaev-Viro state sum invariant of this 3-manifold using a fast but inexact floating-point approximation.
 
const TuraevViroSetallCalculatedTuraevViro () const
 Returns the cache of all Turaev-Viro state sum invariants that have been calculated for this 3-manifold.
 
std::array< long, 3 > longitudeCuts () const
 Identifies the algebraic longitude as a curve on the boundary of a triangulated knot complement.
 
Edge< 3 > * longitude ()
 Modifies a triangulated knot complement so that the algebraic longitude follows a single boundary edge, and returns this edge.
 
Edge< 3 > * meridian ()
 Modifies a triangulated knot complement so that the meridian follows a single boundary edge, and returns this edge.
 
std::pair< Edge< 3 > *, Edge< 3 > * > meridianLongitude ()
 Modifies a triangulated knot complement so that the meridian and algebraic longitude each follow a single boundary edge, and returns these two edges.
 
Normal Surfaces and Angle Structures
template<int subdim>
std::pair< NormalSurface, bool > linkingSurface (const Face< 3, subdim > &face) const
 Returns the link of the given face as a normal surface.
 
bool isZeroEfficient () const
 Determines if this triangulation is 0-efficient.
 
bool knowsZeroEfficient () const
 Is it already known whether or not this triangulation is 0-efficient? See isZeroEfficient() for further details.
 
bool isOneEfficient () const
 Determines if this triangulation is 1-efficient.
 
bool knowsOneEfficient () const
 Is it already known whether or not this triangulation is 1-efficient? See isOneEfficient() for further details.
 
bool hasSplittingSurface () const
 Determines whether this triangulation has a normal splitting surface.
 
std::optional< NormalSurfacenonTrivialSphereOrDisc () const
 Searches for a non-vertex-linking normal sphere or disc within this triangulation.
 
std::optional< NormalSurfaceoctagonalAlmostNormalSphere () const
 Searches for an octagonal almost normal 2-sphere within this triangulation.
 
const AngleStructurestrictAngleStructure () const
 Returns a strict angle structure on this triangulation, if one exists.
 
bool hasStrictAngleStructure () const
 Determines whether this triangulation supports a strict angle structure.
 
bool knowsStrictAngleStructure () const
 Is it already known (or trivial to determine) whether or not this triangulation supports a strict angle structure? See hasStrictAngleStructure() for further details.
 
const AngleStructuregeneralAngleStructure () const
 Returns a generalised angle structure on this triangulation, if one exists.
 
bool hasGeneralAngleStructure () const
 Determines whether this triangulation supports a generalised angle structure.
 
Skeletal Transformations
std::set< Edge< 3 > * > maximalForestInBoundary () const
 Produces a maximal forest in the 1-skeleton of the triangulation boundary.
 
std::set< Edge< 3 > * > maximalForestInSkeleton (bool canJoinBoundaries=true) const
 Produces a maximal forest in the triangulation's 1-skeleton.
 
bool simplify ()
 Attempts to simplify this triangulation as intelligently as possible using fast and greedy heuristics.
 
bool intelligentSimplify ()
 Deprecated alias for simplify(), which attempts to simplify this triangulation as intelligently as possible using fast and greedy heuristics.
 
bool simplifyToLocalMinimum (bool perform=true)
 Uses all known simplification moves to reduce the triangulation monotonically to some local minimum number of tetrahedra.
 
bool simplifyExhaustive (int height=1, int threads=1, ProgressTrackerOpen *tracker=nullptr)
 Attempts to simplify this triangulation using a slow but exhaustive search through the Pachner graph.
 
template<typename Action , typename... Args>
bool retriangulate (int height, int threads, ProgressTrackerOpen *tracker, Action &&action, Args &&... args) const
 Explores all triangulations that can be reached from this via Pachner moves, without exceeding a given number of additional tetrahedra.
 
bool minimiseBoundary ()
 Ensures that the boundary contains the smallest possible number of triangles, potentially adding tetrahedra to do this.
 
bool minimizeBoundary ()
 A deprecated synonym for minimiseBoundary().
 
bool minimiseVertices ()
 Ensures that this triangulation contains the smallest possible number of vertices for the 3-manifold that it represents, potentially adding tetrahedra to do this.
 
bool minimizeVertices ()
 A deprecated synonym for minimiseVertices().
 
bool move44 (Edge< 3 > *e, int axis)
 If possible, performs a 4-4 move about the given edge of this triangulation.
 
bool move21 (Edge< 3 > *e, int edgeEnd)
 If possible, performs a 2-1 move at the given end of the given edge of this triangulation.
 
bool move02 (EdgeEmbedding< 3 > e0, int t0, EdgeEmbedding< 3 > e1, int t1)
 If possible, performs a 0-2 move about the two specified triangles.
 
bool move02 (Edge< 3 > *e, size_t t0, size_t t1)
 If possible, performs a 0-2 move about the two specified triangles.
 
bool move02 (Triangle< 3 > *t0, int e0, Triangle< 3 > *t1, int e1)
 If possible, performs a 0-2 move about the two specified triangles.
 
bool openBook (Triangle< 3 > *t)
 If possible, performs a book opening move about the given triangle.
 
bool closeBook (Edge< 3 > *e)
 If possible, performs a book closing move about the given edge.
 
bool collapseEdge (Edge< 3 > *e)
 If possible, performs an edge collapse move upon the given edge.
 
bool has44 (Edge< 3 > *e, int axis) const
 Determines whether it is possible to perform a 4-4 move about the given edge of this triangulation, without violating any simplex and/or facet locks.
 
bool has21 (Edge< 3 > *e, int edgeEnd) const
 Determines whether it is possible to perform a 2-1 move at the given end of the given edge of this triangulation, without violating any simplex and/or facet locks.
 
bool has02 (EdgeEmbedding< 3 > e0, int t0, EdgeEmbedding< 3 > e1, int t1) const
 Determines whether it is possible to perform a 0-2 move about the two specified triangles of this triangulation, without violating any facet locks.
 
bool has02 (Edge< 3 > *e, size_t t0, size_t t1) const
 Determines whether it is possible to perform a 0-2 move about the two specified triangles of this triangulation, without violating any facet locks.
 
bool has02 (Triangle< 3 > *t0, int e0, Triangle< 3 > *t1, int e1) const
 Determines whether it is possible to perform a 0-2 move about the two given triangles of this triangulation, without violating any facet locks.
 
bool hasOpenBook (Triangle< 3 > *t) const
 Determines whether it is possible to perform a book opening move about the given triangle of this triangulation, without violating any facet locks.
 
bool hasCloseBook (Edge< 3 > *e) const
 Determines whether it is possible to perform a book closing move about the given edge of this triangulation, without violating any facet locks.
 
bool hasCollapseEdge (Edge< 3 > *e) const
 Determines whether it is possible to collapse the given edge of this triangulation, without violating any simplex and/or facet locks.
 
std::optional< Triangulation< 3 > > with44 (Edge< 3 > *e, int axis) const
 If possible, returns the triangulation obtained by performing a 4-4 move about the given edge of this triangulation.
 
std::optional< Triangulation< 3 > > with21 (Edge< 3 > *e, int edgeEnd) const
 If possible, returns the triangulation obtained by performing a 2-1 move at the given end of the given edge of this triangulation.
 
std::optional< Triangulation< 3 > > with02 (EdgeEmbedding< 3 > e0, int t0, EdgeEmbedding< 3 > e1, int t1) const
 If possible, returns the triangulation obtained by performing a 0-2 move about the two specified triangles of this triangulation.
 
std::optional< Triangulation< 3 > > with02 (Edge< 3 > *e, size_t t0, size_t t1) const
 If possible, returns the triangulation obtained by performing a 0-2 move about the two specified triangles of this triangulation.
 
std::optional< Triangulation< 3 > > with02 (Triangle< 3 > *t0, int e0, Triangle< 3 > *t1, int e1) const
 If possible, returns the triangulation obtained by performing a 0-2 move about the two given triangles of this triangulation.
 
std::optional< Triangulation< 3 > > withOpenBook (Triangle< 3 > *t) const
 If possible, returns the triangulation obtained by performing a book opening move about the given triangle of this triangulation.
 
std::optional< Triangulation< 3 > > withCloseBook (Edge< 3 > *e) const
 If possible, returns the triangulation obtained by performing a book closing move about the given edge of this triangulation.
 
std::optional< Triangulation< 3 > > withCollapseEdge (Edge< 3 > *e) const
 If possible, returns the triangulation obtained by collapsing the given edge of this triangulation.
 
bool fourFourMove (Edge< 3 > *e, int axis, bool ignored, bool perform=true)
 Deprecated routine that tests for and optionally performs a 4-4 move about the given edge of this triangulation.
 
bool twoOneMove (Edge< 3 > *e, int edgeEnd, bool ignored, bool perform=true)
 Deprecated routine that tests for and optionally performs a 2-1 move at the given end of the given edge of this triangulation.
 
bool zeroTwoMove (EdgeEmbedding< 3 > e0, int t0, EdgeEmbedding< 3 > e1, int t1, bool ignored, bool perform=true)
 Deprecated routine that tests for and optionally performs a 0-2 move about the two specified triangles of this triangulation.
 
bool zeroTwoMove (Edge< 3 > *e, size_t t0, size_t t1, bool ignored, bool perform=true)
 Deprecated routine that tests for and optionally performs a 0-2 move about the two specified triangles of this triangulation.
 
bool zeroTwoMove (Triangle< 3 > *t0, int e0, Triangle< 3 > *t1, int e1, bool ignored, bool perform=true)
 Deprecated routine that tests for and optionally performs a 0-2 move about the two given triangles of this triangulation.
 
bool openBook (Triangle< 3 > *t, bool ignored, bool perform=true)
 Deprecated routine that tests for and optionally performs a book opening move about the given triangle of this triangulation.
 
bool closeBook (Edge< 3 > *e, bool ignored, bool perform=true)
 Deprecated routine that tests for and optionally performs a book closing move about the given edge of this triangulation.
 
bool collapseEdge (Edge< 3 > *e, bool ignored, bool perform=true)
 Deprecated routine that tests for and optionally performs an edge collapse move upon the given edge of this triangulation.
 
void reorderTetrahedraBFS (bool reverse=false)
 Deprecated alias for reorderBFS(), which reorders the tetrahedra of this triangulation using a breadth-first search.
 
bool order (bool forceOriented=false)
 Relabels tetrahedron vertices in this triangulation to give an ordered triangulation, if possible.
 
Decompositions
std::vector< Triangulation< 3 > > summands () const
 Computes the connected sum decomposition of this triangulation.
 
bool isSphere () const
 Determines whether this is a triangulation of a 3-sphere.
 
bool knowsSphere () const
 Is it already known (or trivial to determine) whether or not this is a triangulation of a 3-sphere? See isSphere() for further details.
 
bool isBall () const
 Determines whether this is a triangulation of a 3-dimensional ball.
 
bool knowsBall () const
 Is it already known (or trivial to determine) whether or not this is a triangulation of a 3-dimensional ball? See isBall() for further details.
 
bool isSolidTorus () const
 Determines whether this is a triangulation of the solid torus; that is, the unknot complement.
 
bool knowsSolidTorus () const
 Is it already known (or trivial to determine) whether or not this is a triangulation of a solid torus (that is, the unknot complement)? See isSolidTorus() for further details.
 
ssize_t recogniseHandlebody () const
 Determines whether this is a triangulation of an orientable handlebody, and if so, which genus.
 
bool knowsHandlebody () const
 Is it already known (or trivial to determine) whether or not this is a triangulation of an orientable handlebody? See recogniseHandlebody() for further details.
 
bool isTxI () const
 Determines whether or not the underlying 3-manifold is the product of a torus with an interval.
 
bool knowsTxI () const
 Is it already known (or trivial to determine) whether or not this is a triangulation of a the product of a torus with an interval? See isTxI() for further details.
 
bool isIrreducible () const
 Determines whether the underlying 3-manifold (which must be closed) is irreducible.
 
bool knowsIrreducible () const
 Is it already known (or trivial to determine) whether or not the underlying 3-manifold is irreducible? See isIrreducible() for further details.
 
bool hasCompressingDisc () const
 Searches for a compressing disc within the underlying 3-manifold.
 
bool knowsCompressingDisc () const
 Is it already known (or trivial to determine) whether or not the underlying 3-manifold contains a compressing disc? See hasCompressingDisc() for further details.
 
bool isHaken () const
 Determines whether the underlying 3-manifold (which must be closed and orientable) is Haken.
 
bool knowsHaken () const
 Is it already known (or trivial to determine) whether or not the underlying 3-manifold is Haken? See isHaken() for further details.
 
bool hasSimpleCompressingDisc () const
 Searches for a "simple" compressing disc inside this triangulation.
 
const TreeDecompositionniceTreeDecomposition () const
 Returns a nice tree decomposition of the face pairing graph of this triangulation.
 
bool improveTreewidth (ssize_t maxAttempts=5000, int height=2, int threads=1, ProgressTrackerOpen *tracker=nullptr)
 Attempts to retriangulate this to have a smaller width tree decomposition.
 
Subdivisions, Extensions and Covers
bool truncateIdeal ()
 Truncates all ideal or invalid vertices, converting these into real boundary components made from unglued faces of tetrahedra.
 
bool idealToFinite ()
 Alias for truncateIdeal(), which truncates all ideal or invalid vertices to convert these into real boundary components.
 
void truncate (Vertex< 3 > *vertex, bool lockBoundary=false)
 Truncates the given vertex.
 
void pinchEdge (Edge< 3 > *e)
 Pinches an internal edge to a point.
 
void puncture (Triangle< 3 > *location=nullptr)
 Punctures this manifold by thickening the given triangle into a triangular pillow and then removing a 3-ball from its interior.
 
void puncture (Tetrahedron< 3 > *tet)
 Deprecated routine that punctures this manifold by removing a 3-ball from the interior of the given tetrahedron.
 
Building Triangulations
Tetrahedron< 3 > * layerOn (Edge< 3 > *edge)
 Performs a layering upon the given boundary edge of the triangulation.
 
bool fillTorus (size_t cuts0, size_t cuts1, size_t cuts2, BoundaryComponent< 3 > *bc=nullptr)
 Fills a two-triangle torus boundary component by attaching a solid torus along a given curve.
 
bool fillTorus (Edge< 3 > *e0, Edge< 3 > *e1, Edge< 3 > *e2, size_t cuts0, size_t cuts1, size_t cuts2)
 Fills a two-triangle torus boundary component by attaching a solid torus along a given curve.
 
Tetrahedron< 3 > * insertLayeredSolidTorus (size_t cuts0, size_t cuts1)
 Inserts a new layered solid torus into the triangulation.
 
void connectedSumWith (const Triangulation &other)
 Forms the connected sum of this triangulation with the given triangulation.
 
Exporting Triangulations
std::string dehydrate () const
 Dehydrates this triangulation into an alphabetical string.
 
std::string snapPea () const
 Returns a string containing the full contents of a SnapPea data file that describes this triangulation.
 
void snapPea (std::ostream &out) const
 Writes the full contents of a SnapPea data file describing this triangulation to the given output stream.
 
bool saveSnapPea (const char *filename) const
 Writes this triangulation to the given file using SnapPea's native file format.
 
std::string recogniser () const
 Returns a string that expresses this triangulation in Matveev's 3-manifold recogniser format.
 
std::string recognizer () const
 A synonym for recogniser().
 
void recogniser (std::ostream &out) const
 Writes a string expressing this triangulation in Matveev's 3-manifold recogniser format to the given output stream.
 
void recognizer (std::ostream &out) const
 A synonym for recognizer(std::ostream&).
 
bool saveRecogniser (const char *filename) const
 Writes this triangulation to the given file in Matveev's 3-manifold recogniser format.
 
bool saveRecognizer (const char *filename) const
 A synonym for saveRecogniser().
 
Simplices
size_t size () const
 Returns the number of top-dimensional simplices in the triangulation.
 
auto simplices () const
 Returns an object that allows iteration through and random access to all top-dimensional simplices in this triangulation.
 
Simplex< dim > * simplex (size_t index)
 Returns the top-dimensional simplex at the given index in the triangulation.
 
const Simplex< dim > * simplex (size_t index) const
 Returns the top-dimensional simplex at the given index in the triangulation.
 
Simplex< dim > * newSimplex ()
 Creates a new top-dimensional simplex and adds it to this triangulation.
 
Simplex< dim > * newSimplex (const std::string &desc)
 Creates a new top-dimensional simplex with the given description and adds it to this triangulation.
 
std::array< Simplex< dim > *, k > newSimplices ()
 Creates k new top-dimensional simplices, adds them to this triangulation, and returns them in a std::array.
 
void newSimplices (size_t k)
 Creates k new top-dimensional simplices and adds them to this triangulation.
 
void removeSimplex (Simplex< dim > *simplex)
 Removes the given top-dimensional simplex from this triangulation.
 
void removeSimplexAt (size_t index)
 Removes the top-dimensional simplex at the given index in this triangulation.
 
void removeAllSimplices ()
 Removes all simplices from the triangulation.
 
void moveContentsTo (Triangulation< dim > &dest)
 Moves the contents of this triangulation into the given destination triangulation, leaving this triangulation empty but otherwise usable.
 
bool hasLocks () const
 Identifies whether any top-dimensional simplices and/or any of their facets are locked.
 
void lockBoundary ()
 Locks all boundary facets of this triangulation.
 
void unlockAll ()
 Unlocks all top-dimensional simplices and their facets.
 
Skeletal Queries
size_t countComponents () const
 Returns the number of connected components in this triangulation.
 
size_t countBoundaryComponents () const
 Returns the number of boundary components in this triangulation.
 
size_t countFaces () const
 Returns the number of subdim-faces in this triangulation.
 
size_t countFaces (int subdim) const
 Returns the number of subdim-faces in this triangulation, where the face dimension does not need to be known until runtime.
 
size_t countVertices () const
 A dimension-specific alias for countFaces<0>().
 
size_t countEdges () const
 A dimension-specific alias for countFaces<1>().
 
size_t countTriangles () const
 A dimension-specific alias for countFaces<2>().
 
size_t countTetrahedra () const
 A dimension-specific alias for countFaces<3>().
 
size_t countPentachora () const
 A dimension-specific alias for countFaces<4>().
 
std::vector< size_t > fVector () const
 Returns the f-vector of this triangulation, which counts the number of faces of all dimensions.
 
auto components () const
 Returns an object that allows iteration through and random access to all components of this triangulation.
 
auto boundaryComponents () const
 Returns an object that allows iteration through and random access to all boundary components of this triangulation.
 
auto faces () const
 Returns an object that allows iteration through and random access to all subdim-faces of this triangulation, in a way that is optimised for C++ programmers.
 
auto faces (int subdim) const
 Returns an object that allows iteration through and random access to all subdim-faces of this triangulation, in a way that is optimised for Python programmers.
 
auto vertices () const
 A dimension-specific alias for faces<0>().
 
auto edges () const
 A dimension-specific alias for faces<1>().
 
auto triangles () const
 A dimension-specific alias for faces<2>(), or an alias for simplices() in dimension dim = 2.
 
auto tetrahedra () const
 A dimension-specific alias for faces<3>(), or an alias for simplices() in dimension dim = 3.
 
auto pentachora () const
 A dimension-specific alias for faces<4>(), or an alias for simplices() in dimension dim = 4.
 
Component< dim > * component (size_t index) const
 Returns the requested connected component of this triangulation.
 
BoundaryComponent< dim > * boundaryComponent (size_t index) const
 Returns the requested boundary component of this triangulation.
 
Face< dim, subdim > * face (size_t index) const
 Returns the requested subdim-face of this triangulation, in a way that is optimised for C++ programmers.
 
auto face (int subdim, size_t index) const
 Returns the requested subdim-face of this triangulation, in a way that is optimised for Python programmers.
 
Face< dim, 0 > * vertex (size_t index) const
 A dimension-specific alias for face<0>().
 
Face< dim, 1 > * edge (size_t index) const
 A dimension-specific alias for face<1>().
 
auto triangle (size_t index)
 A dimension-specific alias for face<2>(), or an alias for simplex() in dimension dim = 2.
 
auto triangle (size_t index) const
 A dimension-specific alias for face<2>(), or an alias for simplex() in dimension dim = 2.
 
auto tetrahedron (size_t index)
 A dimension-specific alias for face<3>(), or an alias for simplex() in dimension dim = 3.
 
auto tetrahedron (size_t index) const
 A dimension-specific alias for face<3>(), or an alias for simplex() in dimension dim = 3.
 
auto pentachoron (size_t index)
 A dimension-specific alias for face<4>(), or an alias for simplex() in dimension dim = 4.
 
auto pentachoron (size_t index) const
 A dimension-specific alias for face<4>(), or an alias for simplex() in dimension dim = 4.
 
Face< dim, subdim > * translate (const Face< dim, subdim > *other) const
 Translates a face of some other triangulation into the corresponding face of this triangulation, using simplex numbers for the translation.
 
FaceEmbedding< dim, subdim > translate (const FaceEmbedding< dim, subdim > &other) const
 Translates a face embedding from some other triangulation into the corresponding face embedding with respect to this triangulation, using simplex numbers for the translation.
 
FacetPairing< dim > pairing () const
 Returns the dual graph of this triangulation, expressed as a facet pairing.
 
Basic Properties
bool isEmpty () const
 Determines whether this triangulation is empty.
 
bool isValid () const
 Determines if this triangulation is valid.
 
bool hasBoundaryFacets () const
 Determines if this triangulation has any boundary facets.
 
size_t countBoundaryFacets () const
 Returns the total number of boundary facets in this triangulation.
 
size_t countBoundaryFaces () const
 Returns the number of boundary subdim-faces in this triangulation.
 
size_t countBoundaryFaces (int subdim) const
 Returns the number of boundary subdim-faces in this triangulation, where the face dimension does not need to be known until runtime.
 
bool isOrientable () const
 Determines if this triangulation is orientable.
 
bool isConnected () const
 Determines if this triangulation is connected.
 
bool isOriented () const
 Determines if this triangulation is oriented; that is, if the vertices of its top-dimensional simplices are labelled in a way that preserves orientation across adjacent facets.
 
long eulerCharTri () const
 Returns the Euler characteristic of this triangulation.
 
Algebraic Properties
const GroupPresentationgroup () const
 Returns the fundamental group of this triangulation.
 
const GroupPresentationfundamentalGroup () const
 An alias for group(), which returns the fundamental group of this triangulation.
 
void setGroupPresentation (GroupPresentation pres)
 Allows the specific presentation of the fundamental group to be changed by some other (external) means.
 
void simplifiedFundamentalGroup (GroupPresentation pres)
 Deprecated alias for setGroupPresentation(), which allows the specific presentation of the fundamental group to be changed by some other (external) means.
 
AbelianGroup homology () const
 Returns the kth homology group of this triangulation, treating any ideal vertices as though they had been truncated.
 
AbelianGroup homology (int k) const
 Returns the kth homology group of this triangulation, treating any ideal vertices as though they had been truncated, where the parameter k does not need to be known until runtime.
 
MarkedAbelianGroup markedHomology () const
 Returns the kth homology group of this triangulation, without truncating ideal vertices, but with explicit coordinates that track the individual k-faces of this triangulation.
 
MarkedAbelianGroup markedHomology (int k) const
 Returns the kth homology group of this triangulation, without truncating ideal vertices, but with explicit coordinates that track the individual k-faces of this triangulation, where the parameter k does not need to be known until runtime.
 
MatrixInt boundaryMap () const
 Returns the boundary map from subdim-faces to (subdim-1)-faces of the triangulation.
 
MatrixInt boundaryMap (int subdim) const
 Returns the boundary map from subdim-faces to (subdim-1)-faces of the triangulation, where the face dimension does not need to be known until runtime.
 
MatrixInt dualBoundaryMap () const
 Returns the boundary map from dual subdim-faces to dual (subdim-1)-faces of the triangulation.
 
MatrixInt dualBoundaryMap (int subdim) const
 Returns the boundary map from dual subdim-faces to dual (subdim-1)-faces of the triangulation, where the face dimension does not need to be known until runtime.
 
MatrixInt dualToPrimal () const
 Returns a map from dual chains to primal chains that preserves homology classes.
 
MatrixInt dualToPrimal (int subdim) const
 Returns a map from dual chains to primal chains that preserves homology classes, where the chain dimension does not need to be known until runtime.
 
Skeletal Transformations
void orient ()
 Relabels the vertices of top-dimensional simplices in this triangulation so that all simplices are oriented consistently, if possible.
 
void reflect ()
 Relabels the vertices of top-dimensional simplices in this triangulation so that all simplices reflect their orientation.
 
void reorderBFS (bool reverse=false)
 Reorders the top-dimensional simplices of this triangulation using a breadth-first search, so that small-numbered simplices are adjacent to other small-numbered simplices.
 
Isomorphism< dim > randomiseLabelling (bool preserveOrientation=true)
 Randomly relabels the top-dimensional simplices and their vertices.
 
bool pachner (Face< dim, k > *f)
 If possible, performs a (dim + 1 - k)-(k + 1) Pachner move about the given k-face.
 
void pachner (Face< dim, k > *f, Unprotected)
 Performs a (dim + 1 - k)-(k + 1) Pachner move about the given k-face, without any safety checks.
 
bool pachner (Face< dim, k > *f, bool ignored, bool perform=true)
 Deprecated routine that tests for and optionally performs a (dim + 1 - k)-(k + 1) Pachner move about the given k-face of this triangulation.
 
bool move20 (Face< dim, k > *f)
 If possible, performs a 2-0 move about the given k-face of degree two.
 
bool shellBoundary (Simplex< dim > *s)
 If possible, performs a boundary shelling move upon the given top-dimensional simplex of this triangulation.
 
bool shellBoundary (Simplex< dim > *s, bool ignored, bool perform=true)
 Deprecated routine that tests for and optionally performs a boundary shelling move on the given top-dimensional simplex.
 
bool hasPachner (Face< dim, k > *f) const
 Determines whether it is possible to perform a (dim + 1 - k)-(k + 1) Pachner move about the given k-face of this triangulation, without violating any simplex and/or facet locks.
 
bool has20 (Face< dim, k > *f) const
 Determines whether it is possible to perform a 2-0 move about the given k-face of this triangulation, without violating any simplex and/or facet locks.
 
bool hasShellBoundary (Simplex< dim > *s) const
 Determines whether it is possible to perform a boundary shelling move upon the given top-dimensional simplex of this triangulation, without violating any simplex and/or facet locks.
 
std::optional< Triangulation< dim > > withPachner (Face< dim, k > *f) const
 If possible, returns the triangulation obtained by performing a (dim + 1 - k)-(k + 1) Pachner move about the given k-face of this triangulation.
 
std::optional< Triangulation< dim > > with20 (Face< dim, k > *f) const
 If possible, returns the triangulation obtained by performing a 2-0 move about the given k-face of this triangulation.
 
std::optional< Triangulation< dim > > withShellBoundary (Simplex< dim > *s) const
 If possible, returns the triangulation obtained by performing a boundary shelling move on the given top-dimensional simplex of this triangulation.
 
bool twoZeroMove (Face< dim, k > *f, bool ignored, bool perform=true)
 Deprecated routine that tests for and optionally performs a 2-0 move about the given k-face of this triangulation.
 
Subdivisions, Extensions and Covers
Triangulation< dim > doubleCover () const
 Returns the orientable double cover of this triangulation.
 
Triangulation< dim > doubleOverBoundary () const
 Returns two copies of this triangulation joined together along their boundary facets.
 
void makeDoubleCover ()
 Deprecated routine that converts this triangulation into its orientable double cover.
 
void subdivide ()
 Does a barycentric subdivision of the triangulation.
 
void barycentricSubdivision ()
 Deprecated routine that performs a barycentric subdivision of the triangulation.
 
bool makeIdeal ()
 Converts each real boundary component into a cusp (i.e., an ideal vertex).
 
bool finiteToIdeal ()
 Alias for makeIdeal(), which converts each real boundary component into an ideal vertex.
 
Decompositions
std::vector< Triangulation< dim > > triangulateComponents () const
 Returns the individual connected components of this triangulation.
 
Isomorphism Testing
bool operator== (const TriangulationBase< dim > &other) const
 Determines if this triangulation is combinatorially identical to the given triangulation.
 
std::optional< Isomorphism< dim > > isIsomorphicTo (const Triangulation< dim > &other) const
 Determines if this triangulation is combinatorially isomorphic to the given triangulation.
 
std::optional< Isomorphism< dim > > isContainedIn (const Triangulation< dim > &other) const
 Determines if an isomorphic copy of this triangulation is contained within the given triangulation, possibly as a subcomplex of some larger component (or components).
 
bool findAllIsomorphisms (const Triangulation< dim > &other, Action &&action, Args &&... args) const
 Finds all ways in which this triangulation is combinatorially isomorphic to the given triangulation.
 
bool findAllSubcomplexesIn (const Triangulation< dim > &other, Action &&action, Args &&... args) const
 Finds all ways in which an isomorphic copy of this triangulation is contained within the given triangulation, possibly as a subcomplex of some larger component (or components).
 
bool makeCanonical ()
 Relabel the top-dimensional simplices and their vertices so that this triangulation is in canonical form.
 
Building Triangulations
void insertTriangulation (const Triangulation< dim > &source)
 Inserts a copy of the given triangulation into this triangulation.
 
void insertTriangulation (Triangulation< dim > &&source)
 Moves the contents of the given triangulation into this triangulation.
 
Exporting Triangulations
void writeTextShort (std::ostream &out) const
 Writes a short text representation of this object to the given output stream.
 
void writeTextLong (std::ostream &out) const
 Writes a detailed text representation of this object to the given output stream.
 
Encoding::Signature isoSig () const
 Constructs the isomorphism signature of the given type for this triangulation.
 
Encoding::Signature sig () const
 Alias for isoSig(), which constructs the isomorphism signature of the given type for this triangulation.
 
std::pair< typename Encoding::Signature, Isomorphism< dim > > isoSigDetail () const
 Constructs the isomorphism signature for this triangulation, along with the relabelling that will occur when the triangulation is reconstructed from it.
 
void tightEncode (std::ostream &out) const
 Writes the tight encoding of this triangulation to the given output stream.
 
std::string source (Language language=Language::Current) const
 Returns C++ or Python source code that can be used to reconstruct this triangulation.
 
std::string dumpConstruction () const
 Deprecated routine that returns C++ code to reconstruct this triangulation.
 
void writeDot (std::ostream &out, bool labels=false) const
 Writes the dual graph of this triangulation in the Graphviz DOT language.
 
std::string dot (bool labels=false) const
 Returns a Graphviz DOT representation of the dual graph of this triangulation.
 

Static Public Member Functions

static Triangulation< dim > tightDecoding (const std::string &enc)
 Reconstructs an object of type T from its given tight encoding.
 

Static Public Attributes

static constexpr int dimension
 A compile-time constant that gives the dimension of the triangulation.
 

Protected Member Functions

void swap (Snapshottable &other) noexcept
 Swap operation.
 
void takeSnapshot ()
 Must be called before modification and/or destruction of the type T contents.
 
bool topologyLocked () const
 Returns whether or not there are any topology locks currently held on this object.
 

Protected Attributes

MarkedVector< Simplex< dim > > simplices_
 The top-dimensional simplices that form the triangulation.
 
MarkedVector< Component< dim > > components_
 The connected components that form the triangulation.
 
MarkedVector< BoundaryComponent< dim > > boundaryComponents_
 The components that form the boundary of the triangulation.
 
std::array< size_t, dim > nBoundaryFaces_
 The number of boundary faces of each dimension.
 
bool valid_
 Is this triangulation valid? See isValid() for details on what this means.
 
PacketHeldBy heldBy_
 Indicates whether this Held object is in fact the inherited data for a PacketOf<Held>.
 
uint8_t topologyLock_ { 0 }
 The number of topology locks currently held on this object.
 

Importing Triangulations

class regina::Face< 3, 3 >
 
class regina::detail::SimplexBase< 3 >
 
class regina::detail::TriangulationBase< 3 >
 
class PacketData< Triangulation< 3 > >
 
class regina::XMLTriangulationReader< 3 >
 
class regina::XMLWriter< Triangulation< 3 > >
 
static Triangulation< 3 > rehydrate (const std::string &dehydration)
 Rehydrates the given alphabetical string into a 3-dimensional triangulation.
 
static Triangulation< 3 > fromSnapPea (const std::string &filenameOrContents)
 Extracts the tetrahedron gluings from the contents of a SnapPea data file.
 

Importing Triangulations

static Triangulation< dim > fromGluings (size_t size, std::initializer_list< std::tuple< size_t, int, size_t, Perm< dim+1 > > > gluings)
 Creates a triangulation from a hard-coded list of gluings.
 
static Triangulation< dim > fromGluings (size_t size, Iterator beginGluings, Iterator endGluings)
 Creates a triangulation from a list of gluings.
 
static Triangulation< dim > fromIsoSig (const std::string &sig)
 Recovers a full triangulation from an isomorphism signature.
 
static Triangulation< dim > fromSig (const std::string &sig)
 Alias for fromIsoSig(), to recover a full triangulation from an isomorphism signature.
 
static size_t isoSigComponentSize (const std::string &sig)
 Deduces the number of top-dimensional simplices in a connected triangulation from its isomorphism signature.
 
static Triangulation< dim > tightDecode (std::istream &input)
 Reconstructs a triangulation from its given tight encoding.
 
Simplex< dim > * newSimplexRaw ()
 A variant of newSimplex() with no management of the underlying triangulation.
 
std::array< Simplex< dim > *, k > newSimplicesRaw ()
 A variant of newSimplices() with no lock management, and no management of the underlying triangulation.
 
void removeSimplexRaw (Simplex< dim > *simplex)
 A variant of removeSimplex() with no lock management, and no management of the underlying triangulation.
 
void ensureSkeleton () const
 Ensures that all "on demand" skeletal objects have been calculated.
 
bool calculatedSkeleton () const
 Determines whether the skeletal objects and properties of this triangulation have been calculated.
 
void cloneSkeleton (const TriangulationBase &src)
 Builds the skeleton of this triangulation as a clone of the skeleton of the given triangulation.
 
void clearBaseProperties ()
 Clears all properties that are managed by this base class.
 
void swapBaseData (TriangulationBase< dim > &other)
 Swaps all data that is managed by this base class, including simplices, skeletal data, cached properties and the snapshotting data, with the given triangulation.
 
void writeXMLBaseProperties (std::ostream &out) const
 Writes a chunk of XML containing properties of this triangulation.
 

Detailed Description

Represents a 3-dimensional triangulation, typically of a 3-manifold.

This is a specialisation of the generic Triangulation class template; see the generic Triangulation documentation for a general overview of how the triangulation classes work. In Python, you can read this generic documentation by looking at a higher dimension: try help(Triangulation5).

This 3-dimensional specialisation offers significant extra functionality, including many functions specific to 3-manifolds.

This class implements C++ move semantics and adheres to the C++ Swappable requirement. It is designed to avoid deep copies wherever possible, even when passing or returning objects by value.

Member Typedef Documentation

◆ PacketChangeGroup

using regina::PacketData< Triangulation< dim > >::PacketChangeGroup
inherited

A type alias for PacketChangeSpan, used when a span is being used purely for optimisation purposes.

This type alias is used in the same way as Packet::PacketChangeGroup: it is purely for the benefit of the human reader, used to indicate that an event span is present purely for optimisation (and in particular, that the code would still be correct without it).

See Packet::PacketChangeGroup for further details.

◆ TuraevViroSet

using regina::Triangulation< 3 >::TuraevViroSet
Initial value:
std::map<std::pair<unsigned long, bool>, Cyclotomic>

A map from (r, parity) pairs to Turaev-Viro invariants, as described by turaevViro().

Constructor & Destructor Documentation

◆ Triangulation() [1/7]

regina::Triangulation< 3 >::Triangulation ( )
default

Default constructor.

Creates an empty triangulation.

◆ Triangulation() [2/7]

regina::Triangulation< 3 >::Triangulation ( const Triangulation< 3 > & src)
inline

Creates a new copy of the given triangulation.

This will also clone any computed properties (such as homology, fundamental group, and so on), as well as the skeleton (vertices, edges, components, etc.). In particular, the same numbering and labelling will be used for all skeletal objects.

If src has any locks on top-dimensional simplices and/or their facets, these locks will also be copied across.

If you want a "clean" copy that resets all properties to unknown, you can use the two-argument copy constructor instead.

Parameters
srcthe triangulation to copy.

◆ Triangulation() [3/7]

regina::Triangulation< 3 >::Triangulation ( const Triangulation< 3 > & src,
bool cloneProps,
bool cloneLocks = true )

Creates a new copy of the given triangulation, with the option of whether or not to clone its computed properties and/or locks also.

If cloneProps is true, then this constructor will also clone any computed properties (such as homology, fundamental group, and so on). If cloneProps is false, then these properties will be marked as unknown in the new triangulation, and will be recomputed on demand if/when they are required.

Regardless of cloneProps, the skeleton (vertices, edges, components, etc.) will always be cloned. This is to ensure that the same numbering and labelling will be used for all skeletal objects in both triangulations.

If cloneLocks is true then any locks on the top-dimensional simplices and/or facets of src will be copied across. If cloneLocks is false then the new triangulation will have no locks at all.

Parameters
srcthe triangulation to copy.
clonePropstrue if this should also clone any computed properties of the given triangulation, or false if the new triangulation should have such properties marked as unknown.
cloneLockstrue if this should also clone any simplex and/or facet locks from the given triangulation, or false if the new triangulation should have no locks at all.

◆ Triangulation() [4/7]

regina::Triangulation< 3 >::Triangulation ( Triangulation< 3 > && src)
defaultnoexcept

Moves the given triangulation into this new triangulation.

This is much faster than the copy constructor, but is still linear time. This is because every tetrahedron must be adjusted to point back to this new triangulation instead of src.

All tetrahedra and skeletal objects (faces, components and boundary components) that belong to src will be moved into this triangulation, and so any pointers or references to Tetrahedron<3>, Face<3, subdim>, Component<3> or BoundaryComponent<3> objects will remain valid. Likewise, all cached properties will be moved into this triangulation.

If src has any locks on top-dimensional simplices and/or their facets, these locks will also be moved across.

The triangulation that is passed (src) will no longer be usable.

Note
This operator is marked noexcept, and in particular does not fire any change events. This is because this triangulation is freshly constructed (and therefore has no listeners yet), and because we assume that src is about to be destroyed (an action that will fire a packet destruction event).
Parameters
srcthe triangulation to move.

◆ Triangulation() [5/7]

regina::Triangulation< 3 >::Triangulation ( const Link & link,
bool simplify = true )

Deprecated constructor that creates a new ideal triangulation representing the complement of the given link diagram.

Deprecated
The preferred way of building the complement of a link diagram is to call Link::complement(). See that routine for further details on exactly what this routine does, including how the tetrahedra will be oriented, and how the construction deals with virtual and/or disconnected link diagrams.
Parameters
linkthe link diagram whose complement we should build.
simplifytrue if and only if the resulting triangulation should be simplified to use as few tetrahedra as possible. This simplification process will preserve the orientations of the tetrahedra.

◆ Triangulation() [6/7]

regina::Triangulation< 3 >::Triangulation ( const std::string & description)

"Magic" constructor that tries to find some way to interpret the given string as a triangulation.

At present, Regina understands the following types of strings (and attempts to parse them in the following order):

This list may grow in future versions of Regina.

Warning
If you pass the filename or contents of a SnapPea data file, then only the tetrahedron gluings will be read; all other SnapPea-specific information (such as peripheral curves) will be lost. See fromSnapPea() for details, and for other alternatives that do preserve SnapPea-specific data.
Exceptions
InvalidArgumentRegina could not interpret the given string as representing a triangulation using any of the supported string types.
Parameters
descriptiona string that describes a 3-manifold triangulation.

◆ Triangulation() [7/7]

regina::Triangulation< 3 >::Triangulation ( snappy::Manifold m)

Python-only constructor that copies the given SnapPy manifold.

Although the argument m would typically be a SnapPy.Manifold, it could in fact be anything with a _to_string() method (so you could instead pass a SnapPy.Triangulation, for example). Regina will then call m._to_string() and pass the result to the "magic" string constructor for Regina's Triangulation3 class. Typically, if m is a SnapPy object, this means that m._to_string() would need to return the contents of a SnapPy/SnapPea data file.

Warning
Only the tetrahedron gluings will be copied; all other SnapPy-specific information (such as peripheral curves) will be lost. See fromSnapPea() for details, and for other alternatives that do preserve SnapPy-specific data.
C++
Not present.
Parameters
ma SnapPy object of type snappy.Manifold.

◆ ~Triangulation()

Destroys this triangulation.

The constituent tetrahedra, the cellular structure and all other properties will also be destroyed.

Member Function Documentation

◆ allCalculatedTuraevViro()

const Triangulation< 3 >::TuraevViroSet & regina::Triangulation< 3 >::allCalculatedTuraevViro ( ) const
inline

Returns the cache of all Turaev-Viro state sum invariants that have been calculated for this 3-manifold.

This cache is updated every time turaevViro() is called, and is emptied whenever the triangulation is modified.

Turaev-Viro invariants are identified by an (r, parity) pair as described in the turaevViro() documentation. The cache is just a set that maps (r, parity) pairs to the corresponding invariant values.

For even values of r, the parity is ignored when calling turaevViro() (since the even and odd versions of the invariant contain essentially the same information). Therefore, in this cache, all even values of r will have the corresponding parities set to false.

Note
All invariants in this cache are now computed using exact arithmetic, as elements of a cyclotomic field. This is a change from Regina 4.96 and earlier, which computed floating-point approximations instead.
Python
This routine returns a Python dictionary. It also returns by value, not by reference (i.e., if more Turaev-Viro invariants are computed later on, the dictionary that was originally returned will not change as a result).
Returns
the cache of all Turaev-Viro invariants that have already been calculated.
See also
turaevViro

◆ anonID()

std::string regina::PacketData< Triangulation< dim > >::anonID ( ) const
inherited

A unique string ID that can be used in place of a packet ID.

This is an alternative to Packet::internalID(), and is designed for use when Held is not actually wrapped by a PacketOf<Held>. (An example of such a scenario is when a normal surface list needs to write its triangulation to file, but the triangulation is a standalone object that is not stored in a packet.)

The ID that is returned will:

  • remain fixed throughout the lifetime of the program for a given object, even if the contents of the object are changed;
  • not clash with the anonID() returned from any other object, or with the internalID() returned from any packet of any type;

These IDs are not preserved when copying or moving one object to another, and are not preserved when writing to a Regina data file and then reloading the file contents.

Warning
If this object is wrapped in a PacketOf<Held>, then anonID() and Packet::internalID() may return different values.

See Packet::internalID() for further details.

Returns
a unique ID that identifies this object.

◆ barycentricSubdivision()

void regina::detail::TriangulationBase< dim >::barycentricSubdivision ( )
inlineinherited

Deprecated routine that performs a barycentric subdivision of the triangulation.

Deprecated
This routine has been renamed to subdivide(), both to shorten the name but also to make it clearer that this triangulation will be modified directly.
Precondition
dim is one of Regina's standard dimensions.
Exceptions
LockViolationThis triangulation contains at least one locked top-dimensional simplex and/or facet. This exception will be thrown before any changes are made. See Simplex<dim>::lock() and Simplex<dim>::lockFacet() for further details on how such locks work and what their implications are.

◆ boundaryComponent()

BoundaryComponent< dim > * regina::detail::TriangulationBase< dim >::boundaryComponent ( size_t index) const
inlineinherited

Returns the requested boundary component of this triangulation.

Note that each time the triangulation changes, all boundary components will be deleted and replaced with new ones. Therefore this object should be considered temporary only.

Parameters
indexthe index of the desired boundary component; this must be between 0 and countBoundaryComponents()-1 inclusive.
Returns
the requested boundary component.

◆ boundaryComponents()

auto regina::detail::TriangulationBase< dim >::boundaryComponents ( ) const
inlineinherited

Returns an object that allows iteration through and random access to all boundary components of this triangulation.

Note that, in Regina's standard dimensions, each ideal vertex forms its own boundary component, and some invalid vertices do also. See the BoundaryComponent class notes for full details on what constitutes a boundary component in standard and non-standard dimensions.

The object that is returned is lightweight, and can be happily copied by value. The C++ type of the object is subject to change, so C++ users should use auto (just like this declaration does).

The returned object is guaranteed to be an instance of ListView, which means it offers basic container-like functions and supports range-based for loops. Note that the elements of the list will be pointers, so your code might look like:

A component of the boundary of a dim-manifold triangulation.
Definition boundarycomponent.h:123
auto boundaryComponents() const
Definition triangulation.h:4929

The object that is returned will remain up-to-date and valid for as long as the triangulation exists. In contrast, however, remember that the individual boundary components within this list will be deleted and replaced each time the triangulation changes. Therefore it is best to treat this object as temporary only, and to call boundaryComponents() again each time you need it.

Returns
access to the list of all boundary components.

◆ boundaryMap() [1/2]

MatrixInt regina::detail::TriangulationBase< dim >::boundaryMap ( ) const
inherited

Returns the boundary map from subdim-faces to (subdim-1)-faces of the triangulation.

For C++ programmers who know subdim at compile time, you should use this template function boundaryMap<subdim>(), which is slightly faster than passing subdim as an ordinary runtime argument to boundaryMap(subdim).

See the non-templated boundaryMap(int) for full details on what this function computes and how the matrix it returns should be interpreted.

Precondition
This triangulation is valid and non-empty.
Python
Not present. Instead use the variant boundaryMap(subdim).
Template Parameters
subdimthe face dimension; this must be between 1 and dim inclusive.
Returns
the boundary map from subdim-faces to (subdim-1)-faces.

◆ boundaryMap() [2/2]

MatrixInt regina::detail::TriangulationBase< dim >::boundaryMap ( int subdim) const
inlineinherited

Returns the boundary map from subdim-faces to (subdim-1)-faces of the triangulation, where the face dimension does not need to be known until runtime.

For C++ programmers who know subdim at compile time, you are better off using the template function boundaryMap<subdim>() instead, which is slightly faster.

This is the boundary map that you would use if you were building the homology groups manually from a chain complex.

Unlike homology(), this code does not use the dual skeleton: instead it uses the primal (i.e., ordinary) skeleton.

  • The main advantage of this is that you can easily match rows and columns of the returned matrix to faces of this triangulation.
  • The main disadvantage is that ideal vertices are not treated as though they were truncated; instead they are just treated as 0-faces that appear as part of the chain complex.

The matrix that is returned should be thought of as acting on column vectors. Specifically, the cth column of the matrix corresponds to the cth subdim-face of this triangulation, and the rth row corresponds to the rth (subdim-1)-face of this triangulation.

For the boundary map, we fix orientations as follows. In simplicial homology, for any k, the orientation of a k-simplex is determined by assigning labels 0,...,k to its vertices. For this routine, since every k-face f is already a k-simplex, these labels will just be the inherent vertex labels 0,...,k of the corresponding Face<k> object. If you need to convert these labels into vertex numbers of a top-dimensional simplex containing f, you can use either Simplex<dim>::faceMapping<k>(), or the equivalent routine FaceEmbedding<k>::vertices().

If you wish to convert these boundary maps to homology groups yourself, either the AbelianGroup class (if you do not need to track which face is which) or the MarkedAbelianGroup class (if you do need to track individual faces) can help you do this.

Note that, unlike many of the templated face-related routines, this routine explicitly supports the case subdim = dim.

Precondition
This triangulation is valid and non-empty.
Exceptions
InvalidArgumentThe face dimension subdim is outside the supported range (i.e., less than 1 or greater than dim).
Parameters
subdimthe face dimension; this must be between 1 and dim inclusive.
Returns
the boundary map from subdim-faces to (subdim-1)-faces.

◆ calculatedSkeleton()

bool regina::detail::TriangulationBase< dim >::calculatedSkeleton ( ) const
inlineprotectedinherited

Determines whether the skeletal objects and properties of this triangulation have been calculated.

These are only calculated "on demand", when a skeletal property is first queried.

Returns
true if and only if the skeleton has been calculated.

◆ clearBaseProperties()

void regina::detail::TriangulationBase< dim >::clearBaseProperties ( )
protectedinherited

Clears all properties that are managed by this base class.

This includes deleting all skeletal objects and emptying the corresponding internal lists, as well as clearing other cached properties and deallocating the corresponding memory where required.

Note that TriangulationBase almost never calls this routine itself (the one exception is the copy assignment operator). Typically clearBaseProperties() is only ever called by Triangulation<dim>::clearAllProperties(), which in turn is called by "atomic" routines that change the triangluation (before firing packet change events), as well as the Triangulation<dim> destructor.

◆ cloneSkeleton()

void regina::detail::TriangulationBase< dim >::cloneSkeleton ( const TriangulationBase< 3 > & src)
protectedinherited

Builds the skeleton of this triangulation as a clone of the skeleton of the given triangulation.

This clones all skeletal objects (e.g., faces, components and boundary components) and skeletal properties (e.g., validity and orientability). In general, this function clones the same properties and data that calculateSkeleton() computes.

For this parent class, cloneSkeleton() clones properties and data that are common to all dimensions. Some Triangulation<dim> subclasses may track additional skeletal properties or data, in which case they should reimplement this function (just as they also reimplement calculateSkeleton()). Their reimplementations must call this parent implementation.

This function is intended only for use by the copy constructor (and related "copy-like" constructors), and the copy assignment operator. Other code should typically not need to call this function directly.

The real point of this routine is to ensure that, when a triangulation is cloned, its skeleton is cloned with exactly the same numbering/labelling of its skeletal objects. To this end, it is fine to leave some "large" skeletal properties to be computed on demand where this is allowed (e.g., triangulated vertex links or triangulated boundary components, which are allowed to remain uncomputed until required, even when the full skeleton has been computed).

Precondition
No skeletal objects have been computed for this triangulation, and the corresponding internal lists are all empty.
The skeleton has been fully computed for the given source triangulation.
The given source triangulation is combinatorially identical to this triangulation (i.e., both triangulations have the same number of top-dimensional simplices, with gluings between the same pairs of numbered simplices using the same gluing permutations).
Warning
Any call to cloneSkeleton() must first cast down to Triangulation<dim>, to ensure that you are catching the subclass implementation if this exists. You should never directly call this parent implementation (unless of course you are reimplementing cloneSkeleton() in a Triangulation<dim> subclass).
Parameters
srcthe triangulation whose skeleton should be cloned.

◆ closeBook() [1/2]

bool regina::Triangulation< 3 >::closeBook ( Edge< 3 > * e)
inline

If possible, performs a book closing move about the given edge.

This involves taking a boundary edge of the triangulation and folding together the two boundary triangles on either side. The resulting effect is to simplify the boundary of the triangulation.

This triangulation will be changed directly.

This move will only be performed if it will not change the topology of the manifold (as discussed below), and it will not violate any facet locks. See Simplex<3>::lockFacet() for further details on facet locks. Note that simplex locks are never a concern for this type of move.

In order for this move to make sense and to not to change the topology, we require that:

  • the given edge e is a boundary edge;
  • the two vertices opposite e in the boundary triangles that contain e are valid and distinct;
  • the boundary component containing e contains more than two triangles.

There are several additional distinctness conditions on the nearby edges and triangles, but they follow automatically from the conditions listed above.

If this triangulation is currently oriented, then this operation will (trivially) preserve the orientation.

Note that after performing this move, all skeletal objects (faces, components, etc.) will be reconstructed, which means any pointers to old skeletal objects (such as the argument e) can no longer be used.

See openBook() for an inverse to this move.

Precondition
The given edge is an edge of this triangulation.
Parameters
ethe edge about which to perform the move.
Returns
true if and only if the requested move was able to be performed.

◆ closeBook() [2/2]

bool regina::Triangulation< 3 >::closeBook ( Edge< 3 > * e,
bool ignored,
bool perform = true )
inline

Deprecated routine that tests for and optionally performs a book closing move about the given edge of this triangulation.

For more details on book closing moves and when they can be performed, see the variant of closeBook() without the extra boolean arguments.

This routine will always check whether the requested move is legal and will not violate any facet locks (see Simplex<3>::lockFacet() for further details on facet locks). Note that this type of move can never violate a simplex lock, and so there is no need to check for those at all. If the move is allowed, and if the argument perform is true, this routine will also perform the move.

Deprecated
If you just wish to test whether such a move is possible, call hasCloseBook(). If you wish to both check and perform the move, call closeBook() without the two extra boolean arguments.
Precondition
The given edge is an edge of this triangulation.
Parameters
ethe edge about which to perform the move.
ignoredan argument that is ignored. In earlier versions of Regina this argument controlled whether we check if the move can be performed; however, now this check is done always.
performtrue if we should actually perform the move, assuming the move is allowed.
Returns
true if and only if the requested move could be performed.

◆ collapseEdge() [1/2]

bool regina::Triangulation< 3 >::collapseEdge ( Edge< 3 > * e)
inline

If possible, performs an edge collapse move upon the given edge.

This involves collapsing the edge to a point, merging its two endpoints together, and flattening all of the tetrahedra that contain it. The resulting effect is to reduce the number of vertices in this triangulation by one.

This triangulation will be changed directly.

This move will only be performed if it will not change the topology of the manifold (as discussed below), and it will not violate any simplex and/or facet locks. See Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on locks.

The requirements for this move to not change the topology are complex, and are discussed in detail in the collapseEdge() source code for those who are interested. The most important requirement is that the given edge should join two distinct vertices. It is also important to note that checking the full requirements is expensive (amongst other things, we need to build a union-find structure to implement the test).

If you are trying to reduce the number of vertices without changing the topology, and if e is an edge connecting an internal vertex with some different vertex, then either collapseEdge() or pinchEdge() may be more appropriate for your situation (though you may find it easier just to call minimiseVertices() instead).

  • The advantage of collapseEdge() is that it decreases the number of tetrahedra, whereas pinchEdge() increases this number (but only by two).
  • The disadvantages of collapseEdge() are that it cannot always be performed, and its validity tests are expensive; pinchEdge() on the other hand can always be used for edges e of the type described above.

If this triangulation is currently oriented, then this operation will preserve the orientation.

Note that after performing this move, all skeletal objects (faces, components, etc.) will be reconstructed, which means any pointers to old skeletal objects (such as the argument e) can no longer be used.

Precondition
The given edge is an edge of this triangulation.
Parameters
ethe edge to collapse.
Returns
true if and only if the requested move was able to be performed.

◆ collapseEdge() [2/2]

bool regina::Triangulation< 3 >::collapseEdge ( Edge< 3 > * e,
bool ignored,
bool perform = true )
inline

Deprecated routine that tests for and optionally performs an edge collapse move upon the given edge of this triangulation.

For more details on edge collapse moves and when they can be performed, as well as the difference between edge collapse and edge pinch moves, see the variant of collapseEdge() without the extra boolean arguments.

This routine will always check whether the requested move is legal and will not violate any simplex and/or facet locks (see Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on locks). If the move is allowed, and if the argument perform is true, this routine will also perform the move.

Deprecated
If you just wish to test whether such a move is possible, call hasCollapseEdge(). If you wish to both check and perform the move, call collapseEdge() without the two extra boolean arguments.
Precondition
The given edge is an edge of this triangulation.
Parameters
ethe edge to collapse.
ignoredan argument that is ignored. In earlier versions of Regina this argument controlled whether we check if the move can be performed; however, now this check is done always.
performtrue if we should actually perform the move, assuming the move is allowed.
Returns
true if and only if the requested move could be performed.

◆ component()

Component< dim > * regina::detail::TriangulationBase< dim >::component ( size_t index) const
inlineinherited

Returns the requested connected component of this triangulation.

Note that each time the triangulation changes, all component objects will be deleted and replaced with new ones. Therefore this component object should be considered temporary only.

Parameters
indexthe index of the desired component; this must be between 0 and countComponents()-1 inclusive.
Returns
the requested component.

◆ components()

auto regina::detail::TriangulationBase< dim >::components ( ) const
inlineinherited

Returns an object that allows iteration through and random access to all components of this triangulation.

The object that is returned is lightweight, and can be happily copied by value. The C++ type of the object is subject to change, so C++ users should use auto (just like this declaration does).

The returned object is guaranteed to be an instance of ListView, which means it offers basic container-like functions and supports range-based for loops. Note that the elements of the list will be pointers, so your code might look like:

for (Component<dim>* c : tri.components()) { ... }
A connected component of a dim-manifold triangulation.
Definition component.h:79
auto components() const
Definition triangulation.h:4923

The object that is returned will remain up-to-date and valid for as long as the triangulation exists. In contrast, however, remember that the individual component objects within this list will be deleted and replaced each time the triangulation changes. Therefore it is best to treat this object as temporary only, and to call components() again each time you need it.

Returns
access to the list of all components.

◆ connectedSumWith()

void regina::Triangulation< 3 >::connectedSumWith ( const Triangulation< 3 > & other)

Forms the connected sum of this triangulation with the given triangulation.

This triangulation will be altered directly.

If this and the given triangulation are both oriented, then the result will be oriented also, and the connected sum will respect these orientations.

If one or both triangulations contains multiple connected components, this routine will connect the components containing tetrahedron 0 of each triangulation, and will copy any additional components across with no modification.

If either triangulation is empty, then the result will simply be a clone of the other triangulation.

This and/or the given triangulation may be bounded or ideal, or even invalid; in all cases the connected sum will be formed correctly. Note, however, that the result might possibly contain internal vertices (even if the original triangulations do not).

Tetrahedron and/or facet locks will not prevent the connected sum from taking place. The operation essentially involves prying open two triangles (one from each triangulation) and joining them with a connector gadget; if some original triangle t is locked then the lock will be pushed across to one of two triangles that results when t is pried open. In particular, if t is a boundary triangle then the lock will be kept on the boundary (as expected).

It is allowed to pass this triangulation as other.

Parameters
otherthe triangulation to sum with this.

◆ countBoundaryComponents()

size_t regina::detail::TriangulationBase< dim >::countBoundaryComponents ( ) const
inlineinherited

Returns the number of boundary components in this triangulation.

Note that, in Regina's standard dimensions, each ideal vertex forms its own boundary component, and some invalid vertices do also. See the BoundaryComponent class notes for full details on what constitutes a boundary component in standard and non-standard dimensions.

Returns
the number of boundary components.

◆ countBoundaryFaces() [1/2]

size_t regina::detail::TriangulationBase< dim >::countBoundaryFaces ( ) const
inlineinherited

Returns the number of boundary subdim-faces in this triangulation.

This is the fastest way to count faces if you know subdim at compile time.

Specifically, this counts the number of subdim-faces for which isBoundary() returns true. This may lead to some unexpected results in non-standard scenarios; see the documentation for the non-templated countBoundaryFaces(int) for details.

Python
Not present. Instead use the variant countBoundaryFaces(subdim).
Template Parameters
subdimthe face dimension; this must be between 0 and dim-1 inclusive.
Returns
the number of boundary subdim-faces.

◆ countBoundaryFaces() [2/2]

size_t regina::detail::TriangulationBase< dim >::countBoundaryFaces ( int subdim) const
inlineinherited

Returns the number of boundary subdim-faces in this triangulation, where the face dimension does not need to be known until runtime.

This routine takes linear time in the dimension dim. For C++ programmers who know subdim at compile time, you are better off using the template function countBoundaryFaces<subdim>() instead, which is fast constant time.

Specifically, this counts the number of subdim-faces for which isBoundary() returns true. This may lead to some unexpected results in non-standard scenarios; for example:

  • In non-standard dimensions, ideal vertices are not recognised and so will not be counted as boundary;
  • In an invalid triangulation, the number of boundary faces reported here may be smaller than the number of faces obtained when you triangulate the boundary using BoundaryComponent::build(). This is because "pinched" faces (where separate parts of the boundary are identified together) will only be counted once here, but will "spring apart" into multiple faces when the boundary is triangulated.
Exceptions
InvalidArgumentThe face dimension subdim is outside the supported range (i.e., negative or greater than dim-1).
Parameters
subdimthe face dimension; this must be between 0 and dim-1 inclusive.
Returns
the number of boundary subdim-faces.

◆ countBoundaryFacets()

size_t regina::detail::TriangulationBase< dim >::countBoundaryFacets ( ) const
inlineinherited

Returns the total number of boundary facets in this triangulation.

This routine counts facets of top-dimensional simplices that are not glued to some adjacent top-dimensional simplex.

This is equivalent to calling countBoundaryFaces<dim-1>().

Returns
the total number of boundary facets.

◆ countBoundaryTriangles()

size_t regina::Triangulation< 3 >::countBoundaryTriangles ( ) const
inline

A dimension-specific alias for countBoundaryFacets().

See countBoundaryFacets() for further information.

◆ countComponents()

size_t regina::detail::TriangulationBase< dim >::countComponents ( ) const
inlineinherited

Returns the number of connected components in this triangulation.

Returns
the number of connected components.

◆ countEdges()

size_t regina::detail::TriangulationBase< dim >::countEdges ( ) const
inlineinherited

A dimension-specific alias for countFaces<1>().

This alias is available for all dimensions dim.

See countFaces() for further information.

◆ countFaces() [1/2]

size_t regina::detail::TriangulationBase< dim >::countFaces ( ) const
inlineinherited

Returns the number of subdim-faces in this triangulation.

This is the fastest way to count faces if you know subdim at compile time.

For convenience, this routine explicitly supports the case subdim = dim. This is not the case for the routines face() and faces(), which give access to individual faces (the reason relates to the fact that top-dimensional simplices are built manually, whereas lower-dimensional faces are deduced properties).

Python
Not present. Instead use the variant countFaces(subdim).
Template Parameters
subdimthe face dimension; this must be between 0 and dim inclusive.
Returns
the number of subdim-faces.

◆ countFaces() [2/2]

size_t regina::detail::TriangulationBase< dim >::countFaces ( int subdim) const
inlineinherited

Returns the number of subdim-faces in this triangulation, where the face dimension does not need to be known until runtime.

This routine takes linear time in the dimension dim. For C++ programmers who know subdim at compile time, you are better off using the template function countFaces<subdim>() instead, which is fast constant time.

For convenience, this routine explicitly supports the case subdim = dim. This is not the case for the routines face() and faces(), which give access to individual faces (the reason relates to the fact that top-dimensional simplices are built manually, whereas lower-dimensional faces are deduced properties).

Exceptions
InvalidArgumentThe face dimension subdim is outside the supported range (i.e., negative or greater than dim).
Parameters
subdimthe face dimension; this must be between 0 and dim inclusive.
Returns
the number of subdim-faces.

◆ countPentachora()

size_t regina::detail::TriangulationBase< dim >::countPentachora ( ) const
inlineinherited

A dimension-specific alias for countFaces<4>().

This alias is available for dimensions dim ≥ 4.

See countFaces() for further information.

◆ countTetrahedra()

size_t regina::detail::TriangulationBase< dim >::countTetrahedra ( ) const
inlineinherited

A dimension-specific alias for countFaces<3>().

This alias is available for dimensions dim ≥ 3.

See countFaces() for further information.

◆ countTriangles()

size_t regina::detail::TriangulationBase< dim >::countTriangles ( ) const
inlineinherited

A dimension-specific alias for countFaces<2>().

This alias is available for all dimensions dim.

See countFaces() for further information.

◆ countVertices()

size_t regina::detail::TriangulationBase< dim >::countVertices ( ) const
inlineinherited

A dimension-specific alias for countFaces<0>().

This alias is available for all dimensions dim.

See countFaces() for further information.

◆ dehydrate()

std::string regina::Triangulation< 3 >::dehydrate ( ) const

Dehydrates this triangulation into an alphabetical string.

A dehydration string is a compact text representation of a triangulation, introduced by Callahan, Hildebrand and Weeks for their cusped hyperbolic census (see below). The dehydration string of an n-tetrahedron triangulation consists of approximately (but not precisely) 5n/2 lower-case letters.

Dehydration strings come with some restrictions:

  • They rely on the triangulation being "canonical" in some combinatorial sense. This is not enforced here; instead a combinatorial isomorphism is applied to make the triangulation canonical, and this isomorphic triangulation is dehydrated instead. Note that the original triangulation is not changed.
  • They require the triangulation to be connected.
  • They require the triangulation to have no boundary triangles (though ideal triangulations are fine).
  • They can only support triangulations with at most 25 tetrahedra.

The routine rehydrate() can be used to recover a triangulation from a dehydration string. Note that the triangulation recovered might not be identical to the original, but it is guaranteed to be an isomorphic copy.

For a full description of the dehydrated triangulation format, see A Census of Cusped Hyperbolic 3-Manifolds, Callahan, Hildebrand and Weeks, Mathematics of Computation 68/225, 1999.

Exceptions
NotImplementedEither this triangulation is disconnected, it has boundary triangles, or it contains more than 25 tetrahedra.
Returns
a dehydrated representation of this triangulation (or an isomorphic variant of this triangulation).

◆ detail()

std::string regina::Output< Triangulation< dim >, false >::detail ( ) const
inherited

Returns a detailed text representation of this object.

This text may span many lines, and should provide the user with all the information they could want. It should be human-readable, should not contain extremely long lines (which cause problems for users reading the output in a terminal), and should end with a final newline. There are no restrictions on the underlying character set.

Returns
a detailed text representation of this object.

◆ dot()

std::string regina::detail::TriangulationBase< dim >::dot ( bool labels = false) const
inlineinherited

Returns a Graphviz DOT representation of the dual graph of this triangulation.

Every vertex of this graph represents a top-dimensional simplex, and every edge represents a pair of simplex facets that are joined together. Note that for a closed triangulation this graph will be entirely (dim + 1)-valent; for triangulations with boundary facets, some graph vertices will have degree dim or less.

The output from this routine can be used as a standalone DOT file, ready for use with Graphviz. This DOT file will describe an undirected graph, and should be used with either the neato or fdp programs shipped with Graphviz.

The functions Triangulation<dim>::dot() and FacetPairing<dim>::dot() differ in a few ways:

  • Triangulation<dim>::dot() does not support subgraph output (where you construct a large DOT file containing the dual graphs of many independent triangulations). If you need subgraph output, you can always call pairing().dot() instead.
  • Triangulation<dim>::dot() makes more use of colour, in particular to indicate locked top-dimensional simplices and/or facets.

If you are simply writing this string to an output stream then you should call writeDot() instead, which is more efficient.

Parameters
labelsindicates whether graph vertices will be labelled with the corresponding simplex numbers.
Returns
the output of writeDot(), as outlined above.

◆ doubleCover()

Triangulation< dim > regina::detail::TriangulationBase< dim >::doubleCover ( ) const
inherited

Returns the orientable double cover of this triangulation.

Each orientable component will be duplicated, and each non-orientable component will be converted into its orientable double cover.

In general, the resulting double cover will not be oriented (though of course it will always be orientable).

If this triangulation has locks on any top-dimensional simplices and/or their facets, then these locks will be duplicated alongside their corresponding simplices and/or facets (i.e., they will appear in both sheets of the double cover).

Returns
the orientable double cover.

◆ doubleOverBoundary()

Triangulation< dim > regina::detail::TriangulationBase< dim >::doubleOverBoundary ( ) const
inherited

Returns two copies of this triangulation joined together along their boundary facets.

Specifically: the resulting triangulation is obtained by taking two copies S and T of this triangulation, and then gluing each boundary facet of S to the corresponding boundary facet of T using the identity permutation.

Any ideal vertices will be left alone (i.e., the ideal boundary components of S and T will not be joined together).

The resulting triangulation will not have any boundary facets. It will also not be oriented, even if this original triangulation is oriented, since S and T will be reflections of each other through the original triangulation boundary.

If this triangulation has no boundary facets (even if it does have ideal boundary components, then the result will simply be two disjoint copies of this original triangulation.

If this triangulation has locks on any top-dimensional simplices and/or their facets, then these locks will be duplicated alongside their corresponding simplices and/or facets (i.e., they will appear in both copies of the original triangulation). Any locks on boundary facets will not prevent this operation from completing successfully (i.e., they will not prevent the two copies S and T from being glued together).

Returns
two copies of this triangulation joined along their boundary facets.

◆ dualBoundaryMap() [1/2]

MatrixInt regina::detail::TriangulationBase< dim >::dualBoundaryMap ( ) const
inherited

Returns the boundary map from dual subdim-faces to dual (subdim-1)-faces of the triangulation.

For C++ programmers who know subdim at compile time, you should use this template function dualBoundaryMap<subdim>(), which is slightly faster than passing subdim as an ordinary runtime argument to dualBoundaryMap(subdim).

See the non-templated dualBoundaryMap(int) for full details on what this function computes and how the matrix it returns should be interpreted.

Precondition
This triangulation is valid and non-empty.
Python
Not present. Instead use the variant dualBoundaryMap(subdim).
Template Parameters
subdimthe dual face dimension; this must be between 1 and dim inclusive if dim is one of Regina's standard dimensions, or between 1 and (dim - 1) inclusive otherwise.
Returns
the boundary map from dual subdim-faces to dual (subdim-1)-faces.

◆ dualBoundaryMap() [2/2]

MatrixInt regina::detail::TriangulationBase< dim >::dualBoundaryMap ( int subdim) const
inlineinherited

Returns the boundary map from dual subdim-faces to dual (subdim-1)-faces of the triangulation, where the face dimension does not need to be known until runtime.

For C++ programmers who know subdim at compile time, you are better off using the template function dualBoundaryMap<subdim>() instead, which is slightly faster.

This function is analogous to boundaryMap(), but is designed to work with dual faces instead of ordinary (primal) faces. In particular, this is used in the implementation of homology(), which works with the dual skeleton in order to effectively truncate ideal vertices.

The matrix that is returned should be thought of as acting on column vectors. Specifically, the cth column of the matrix corresponds to the cth dual subdim-face of this triangulation, and the rth row corresponds to the rth dual (subdim-1)-face of this triangulation. Here we index dual faces in the same order as the (primal) faces of the triangulation that they are dual to, except that we omit primal boundary faces (i.e., primal faces for which Face::isBoundary() returns true). Therefore, for triangulations with boundary, the dual face indices and the corresponding primal face indices might not be equal.

For this dual boundary map, for positive dual face dimensions k, we fix the orientations of the dual k-faces as follows:

  • In simplicial homology, the orientation of a k-simplex is determined by assigning labels 0,...,k to its vertices.
  • Consider a dual k-face d, and let this be dual to the primal (dim-k)-face f. In general, d will not be a simplex. Let B denote the barycentre of f (which also appears as the "centre" point of d).
  • Let emb be an arbitrary FaceEmbedding<dim-k> for f (i.e., chosen from f.embeddings()), and let s be the corresponding top-dimensional simplex containing f (i.e., emb.simplex()). For the special case of dual edges (k = 1), this choice matters; here we choose emb to be the first embedding (that is, f.front()). For larger k this choice does not matter; see below for the reasons why.
  • Now consider how d intersects the top-dimensional simplex s. This intersection is a k-polytope with B as one of its vertices. We can extend this polytope away from B, pushing it all the way through the simplex s, until it becomes a k-simplex g whose vertices are B along with the k "unused" vertices of s that do not appear in f.
  • We can now define the orientation of the dual k-face d to be the orientation of this k-simplex g that contains it. All that remains now is to orient g by choosing a labelling 0,...,k for its vertices.
  • To orient g, we assign the label 0 to B, and we assign the labels 1,...,k to the "unused" vertices v[dim-k+1],...,v[dim] of s respectively, where v is the permutation emb.vertices().
  • Finally, we note that for k > 1, the orientation for d does not depend on the particular choice of s and emb: by the preconditions and the fact that this routine only considers duals of non-boundary faces, the link of f must be a sphere, and therefore the images of those "other" vertices are fixed in a way that preserves orientation as you walk around the link. See the documentation for Simplex<dim>::faceMapping() for details.
  • For the special case of dual edges (k = 1), the conditions above can be described more simply: the two endpoints of the dual edge d correspond to the two top-dimensional simplices on either side of the (dim-1)-face f, and we orient d by labelling these endpoints (0, 1) in the order (f.back(), f.front()).

If you wish to convert these boundary maps to homology groups yourself, either the AbelianGroup class (if you do not need to track which dual face is which) or the MarkedAbelianGroup class (if you do need to track individual dual faces) can help you do this.

Precondition
This triangulation is valid and non-empty.
Exceptions
InvalidArgumentThe face dimension subdim is outside the supported range (as documented for the subdim argument below).
Parameters
subdimthe dual face dimension; this must be between 1 and dim inclusive if dim is one of Regina's standard dimensions, or between 1 and (dim - 1) inclusive otherwise.
Returns
the boundary map from dual subdim-faces to dual (subdim-1)-faces.

◆ dualToPrimal() [1/2]

MatrixInt regina::detail::TriangulationBase< dim >::dualToPrimal ( ) const
inherited

Returns a map from dual chains to primal chains that preserves homology classes.

For C++ programmers who know subdim at compile time, you should use this template function dualToPrimal<subdim>(), which is slightly faster than passing subdim as an ordinary runtime argument to dualToPrimal(subdim).

See the non-templated dualToPrimal(int) for full details on what this function computes and how the matrix it returns should be interpreted.

Precondition
This trianguation is valid, non-empty, and non-ideal. Note that Regina can only detect ideal triangulations in standard dimensions; for higher dimensions it is the user's reponsibility to confirm this some other way.
Python
Not present. Instead use the variant dualToPrimal(subdim).
Template Parameters
subdimthe chain dimension; this must be between 0 and (dim - 1) inclusive.
Returns
the map from dual subdim-chains to primal subdim-chains.

◆ dualToPrimal() [2/2]

MatrixInt regina::detail::TriangulationBase< dim >::dualToPrimal ( int subdim) const
inlineinherited

Returns a map from dual chains to primal chains that preserves homology classes, where the chain dimension does not need to be known until runtime.

For C++ programmers who know subdim at compile time, you are better off using the template function dualToPrimal<subdim>() instead, which is slightly faster.

The matrix that is returned should be thought of as acting on column vectors. Specifically, the cth column of the matrix corresponds to the cth dual subdim-face of this triangulation, and the rth row corresponds to the rth primal subdim-face of this triangulation.

We index and orient these dual and primal faces in the same manner as dualBoundaryMap() and boundaryMap() respectively. In particular, dual faces are indexed in the same order as the primal (dim-subdim)-faces of the triangulation that they are dual to, except that we omit primal boundary faces. See dualBoundaryMap() and boundaryMap() for further details.

The key feature of this map is that, if a column vector v represents a cycle c in the dual chain complex (i.e., it is a chain with zero boundary), and if this map is represented by the matrix M, then the vector M×v represents a cycle in the primal chain complex that belongs to the same subdimth homology class as c.

Regarding implementation: the map is constructed by (i) subdividing each dual face into smaller subdim-simplices whose vertices are barycentres of primal faces of different dimensions, (ii) moving each barycentre to vertex 0 of the corresponding face, and then (iii) discarding any resulting simplices with repeated vertices (which become "flattened" to a dimension less than subdim).

Precondition
This trianguation is valid, non-empty, and non-ideal. Note that Regina can only detect ideal triangulations in standard dimensions; for higher dimensions it is the user's reponsibility to confirm this some other way.
Exceptions
InvalidArgumentThe chain dimension subdim is outside the supported range (as documented for the subdim argument below).
Parameters
subdimthe chain dimension; this must be between 0 and (dim - 1) inclusive.
Returns
the map from dual subdim-chains to primal subdim-chains.

◆ dumpConstruction()

std::string regina::detail::TriangulationBase< dim >::dumpConstruction ( ) const
inherited

Deprecated routine that returns C++ code to reconstruct this triangulation.

Deprecated
This is equivalent to calling source(Language::Cxx), for compatibility with older versions of Regina. In particular, it is not equivalent to calling source() (which defaults to the programming language currently being used). See source() for further details.
Returns
the C++ code that was generated.

◆ edge()

Face< dim, 1 > * regina::detail::TriangulationBase< dim >::edge ( size_t index) const
inlineinherited

A dimension-specific alias for face<1>().

This alias is available for all dimensions dim.

See face() for further information.

◆ edges()

auto regina::detail::TriangulationBase< dim >::edges ( ) const
inlineinherited

A dimension-specific alias for faces<1>().

This alias is available for all dimensions dim.

See faces() for further information.

◆ ensureSkeleton()

void regina::detail::TriangulationBase< dim >::ensureSkeleton ( ) const
inlineprotectedinherited

Ensures that all "on demand" skeletal objects have been calculated.

◆ eulerCharManifold()

long regina::Triangulation< 3 >::eulerCharManifold ( ) const

Returns the Euler characteristic of the corresponding compact 3-manifold.

Instead of simply calculating V-E+F-T, this routine also:

  • treats ideal vertices as surface boundary components (i.e., effectively truncates them);
  • truncates invalid boundary vertices (i.e., boundary vertices whose links are not discs);
  • truncates the projective plane cusps at the midpoints of invalid edges (edges identified with themselves in reverse).

For ideal triangulations, this routine therefore computes the proper Euler characteristic of the manifold (unlike eulerCharTri(), which does not).

For triangulations whose vertex links are all spheres or discs, this routine and eulerCharTri() give identical results.

Returns
the Euler characteristic of the corresponding compact manifold.

◆ eulerCharTri()

long regina::detail::TriangulationBase< dim >::eulerCharTri ( ) const
inlineinherited

Returns the Euler characteristic of this triangulation.

This will be evaluated strictly as the alternating sum of the number of i-faces (that is, countVertices() - countEdges() + countTriangles() - ...).

Note that this routine handles ideal triangulations in a non-standard way. Since it computes the Euler characteristic of the triangulation (and not the underlying manifold), this routine will treat each ideal boundary component as a single vertex, and not as an entire (dim-1)-dimensional boundary component.

In Regina's standard dimensions, for a routine that handles ideal boundary components properly (by treating them as (dim-1)-dimensional boundary components when computing Euler characteristic), you can use the routine eulerCharManifold() instead.

Returns
the Euler characteristic of this triangulation.

◆ face() [1/2]

auto regina::detail::TriangulationBase< dim >::face ( int subdim,
size_t index ) const
inlineinherited

Returns the requested subdim-face of this triangulation, in a way that is optimised for Python programmers.

For C++ users, this routine is not very useful: since precise types must be know at compile time, this routine returns a std::variant v that could store a pointer to any class Face<dim, ...>. This means you cannot access the face directly: you will still need some kind of compile-time knowledge of subdim before you can extract and use an appropriate Face<dim, subdim> object from v. However, once you know subdim at compile time, you are better off using the (simpler and faster) routine face<subdim>() instead.

For Python users, this routine is much more useful: the return type can be chosen at runtime, and so this routine simply returns a Face<dim, subdim> object of the appropriate face dimension that you can use immediately.

The specific return type for C++ programmers will be std::variant<Face<dim, 0>*, ..., Face<dim, dim-1>*>.

Exceptions
InvalidArgumentThe face dimension subdim is outside the supported range (i.e., negative, or greater than or equal to dim).
Parameters
subdimthe face dimension; this must be between 0 and dim-1 inclusive.
indexthe index of the desired face, ranging from 0 to countFaces<subdim>()-1 inclusive.
Returns
the requested face.

◆ face() [2/2]

Face< dim, subdim > * regina::detail::TriangulationBase< dim >::face ( size_t index) const
inlineinherited

Returns the requested subdim-face of this triangulation, in a way that is optimised for C++ programmers.

Python
Not present. Instead use the variant face(subdim, index).
Template Parameters
subdimthe face dimension; this must be between 0 and dim-1 inclusive.
Parameters
indexthe index of the desired face, ranging from 0 to countFaces<subdim>()-1 inclusive.
Returns
the requested face.

◆ faces() [1/2]

auto regina::detail::TriangulationBase< dim >::faces ( ) const
inlineinherited

Returns an object that allows iteration through and random access to all subdim-faces of this triangulation, in a way that is optimised for C++ programmers.

The object that is returned is lightweight, and can be happily copied by value. The C++ type of the object is subject to change, so C++ users should use auto (just like this declaration does).

The returned object is guaranteed to be an instance of ListView, which means it offers basic container-like functions and supports range-based for loops. Note that the elements of the list will be pointers, so your code might look like:

for (Face<dim, subdim>* f : tri.faces<subdim>()) { ... }
Represents a subdim-face in the skeleton of a dim-dimensional triangulation.
Definition face.h:116
auto faces() const
Definition triangulation.h:4936

The object that is returned will remain up-to-date and valid for as long as the triangulation exists. In contrast, however, remember that the individual faces within this list will be deleted and replaced each time the triangulation changes. Therefore it is best to treat this object as temporary only, and to call faces() again each time you need it.

Python
Not present. Instead use the variant faces(subdim).
Template Parameters
subdimthe face dimension; this must be between 0 and dim-1 inclusive.
Returns
access to the list of all subdim-faces.

◆ faces() [2/2]

auto regina::detail::TriangulationBase< dim >::faces ( int subdim) const
inlineinherited

Returns an object that allows iteration through and random access to all subdim-faces of this triangulation, in a way that is optimised for Python programmers.

C++ users should not use this routine. The return type must be fixed at compile time, and so it is a std::variant that can hold any of the lightweight return types from the templated faces<subdim>() function. This means that the return value will still need compile-time knowledge of subdim to extract and use the appropriate face objects. However, once you know subdim at compile time, you are much better off using the (simpler and faster) routine faces<subdim>() instead.

For Python users, this routine is much more useful: the return type can be chosen at runtime, and so this routine returns a Python list of Face<dim, subdim> objects (holding all the subdim-faces of the triangulation), which you can use immediately.

Exceptions
InvalidArgumentThe face dimension subdim is outside the supported range (i.e., negative, or greater than or equal to dim).
Parameters
subdimthe face dimension; this must be between 0 and dim-1 inclusive.
Returns
access to the list of all subdim-faces.

◆ fillTorus() [1/2]

bool regina::Triangulation< 3 >::fillTorus ( Edge< 3 > * e0,
Edge< 3 > * e1,
Edge< 3 > * e2,
size_t cuts0,
size_t cuts1,
size_t cuts2 )

Fills a two-triangle torus boundary component by attaching a solid torus along a given curve.

The three edges of the boundary component should be passed as the arguments e0, e1 and e2. The boundary component will then be filled with a solid torus whose meridional curve cuts these three edges cuts0, cuts1 and cuts2 times respectively.

For the filling to be performed successfully, the three given edges must belong to the same boundary component, and this boundary component must be a two-triangle torus. Moreover, the integers cuts0, cuts1 and cuts2 must be coprime, and two of them must add to give the third. If any of these conditions are not met, then this routine will do nothing and return false.

The triangulation will be simplified before returning.

There are two versions of fillTorus(); the other takes a boundary component, and sets e0, e1 and e2 to its three edges according to Regina's own edge numbering. This version of fillTorus() should be used when you know how the filling curve cuts each boundary edge but you do not know how these edges are indexed in the corresponding boundary component.

Parameters
e0one of the three edges of the boundary component to fill.
e1the second of the three edges of the boundary component to fill.
e2the second of the three edges of the boundary component to fill.
cuts0the number of times that the meridional curve of the new solid torus should cut the edge e0.
cuts1the number of times that the meridional curve of the new solid torus should cut the edge e1.
cuts2the number of times that the meridional curve of the new solid torus should cut the edge e2.
Returns
true if the boundary component was filled successfully, or false if one of the required conditions as described above is not satisfied.

◆ fillTorus() [2/2]

bool regina::Triangulation< 3 >::fillTorus ( size_t cuts0,
size_t cuts1,
size_t cuts2,
BoundaryComponent< 3 > * bc = nullptr )

Fills a two-triangle torus boundary component by attaching a solid torus along a given curve.

The boundary component to be filled should be passed as the argument bc; if the triangulation has exactly one boundary component then you may omit bc (i.e., pass null), and the (unique) boundary component will be inferred.

If the boundary component cannot be inferred, and/or if the selected boundary component is not a two-triangle torus, then this routine will do nothing and return false.

Otherwise the given boundary component will be filled with a solid torus whose meridional curve cuts the edges bc->edge(0), bc->edge(1) and bc->edge(2) a total of cuts0, cuts1 and cuts2 times respectively.

For the filling to be performed successfully, the integers cuts0, cuts1 and cuts2 must be coprime, and two of them must add to give the third. Otherwise, as above, this routine will do nothing and return false.

The triangulation will be simplified before returning.

There are two versions of fillTorus(); the other takes three explicit edges instead of a boundary component. You should use the other version if you know how the filling curve cuts each boundary edge but you do not know how these edges are indexed in the boundary component.

Parameters
cuts0the number of times that the meridional curve of the new solid torus should cut the edge bc->edge(0).
cuts1the number of times that the meridional curve of the new solid torus should cut the edge bc->edge(1).
cuts2the number of times that the meridional curve of the new solid torus should cut the edge bc->edge(2).
bcthe boundary component to fill. If the triangulation has precisely one boundary component then this may be null.
Returns
true if the boundary component was filled successfully, or false if one of the required conditions as described above is not satisfied.

◆ findAllIsomorphisms()

bool regina::detail::TriangulationBase< dim >::findAllIsomorphisms ( const Triangulation< dim > & other,
Action && action,
Args &&... args ) const
inlineinherited

Finds all ways in which this triangulation is combinatorially isomorphic to the given triangulation.

This routine behaves identically to isIsomorphicTo(), except that instead of returning just one isomorphism, all such isomorphisms will be found and processed. See the isIsomorphicTo() notes for details on this.

For each isomorphism that is found, this routine will call action (which must be a function or some other callable object).

  • The first argument to action must be of type (const Isomorphism<dim>&); this will be a reference to the isomorphism that was found. If action wishes to keep the isomorphism, it should take a deep copy (not a reference), since the isomorphism may be changed and reused after action returns.
  • If there are any additional arguments supplied in the list args, then these will be passed as subsequent arguments to action.
  • action must return a bool. A return value of false indicates that the search for isomorphisms should continue, and a return value of true indicates that the search should terminate immediately.
  • This triangulation must remain constant while the search runs (i.e., action must not modify the triangulation).
Warning
For large dimensions, this routine can become extremely slow: its running time includes a factor of (dim+1)!.
Python
There are two versions of this function available in Python. The first form is findAllIsomorphisms(other, action), which mirrors the C++ function: it takes action which may be a pure Python function, the return value indicates whether action ever terminated the search, but it does not take an additonal argument list (args). The second form is findAllIsomorphisms(other), which returns a Python list containing all of the isomorphisms that were found.
Parameters
otherthe triangulation to compare with this one.
actiona function (or other callable object) to call for each isomorphism that is found.
argsany additional arguments that should be passed to action, following the initial isomorphism argument.
Returns
true if action ever terminated the search by returning true, or false if the search was allowed to run to completion.

◆ findAllSubcomplexesIn()

bool regina::detail::TriangulationBase< dim >::findAllSubcomplexesIn ( const Triangulation< dim > & other,
Action && action,
Args &&... args ) const
inlineinherited

Finds all ways in which an isomorphic copy of this triangulation is contained within the given triangulation, possibly as a subcomplex of some larger component (or components).

This routine behaves identically to isContainedIn(), except that instead of returning just one isomorphism (which may be boundary incomplete and need not be onto), all such isomorphisms will be found and processed. See the isContainedIn() notes for details on this.

For each isomorphism that is found, this routine will call action (which must be a function or some other callable object).

  • The first argument to action must be of type (const Isomorphism<dim>&); this will be a reference to the isomorphism that was found. If action wishes to keep the isomorphism, it should take a deep copy (not a reference), since the isomorphism may be changed and reused after action returns.
  • If there are any additional arguments supplied in the list args, then these will be passed as subsequent arguments to action.
  • action must return a bool. A return value of false indicates that the search for isomorphisms should continue, and a return value of true indicates that the search should terminate immediately.
  • This triangulation must remain constant while the search runs (i.e., action must not modify the triangulation).
Warning
For large dimensions, this routine can become extremely slow: its running time includes a factor of (dim+1)!.
Python
There are two versions of this function available in Python. The first form is findAllSubcomplexesIn(other, action), which mirrors the C++ function: it takes action which may be a pure Python function, the return value indicates whether action ever terminated the search, but it does not take an additonal argument list (args). The second form is findAllSubcomplexesIn(other), which returns a Python list containing all of the isomorphisms that were found.
Parameters
otherthe triangulation in which to search for isomorphic copies of this triangulation.
actiona function (or other callable object) to call for each isomorphism that is found.
argsany additional arguments that should be passed to action, following the initial isomorphism argument.
Returns
true if action ever terminated the search by returning true, or false if the search was allowed to run to completion.

◆ finiteToIdeal()

bool regina::detail::TriangulationBase< dim >::finiteToIdeal ( )
inlineinherited

Alias for makeIdeal(), which converts each real boundary component into an ideal vertex.

This alias finiteToIdeal() is provided for compatibility with older versions of Regina. (It is not deprecated, and so this alias should remain part of Regina for a long time.)

See makeIdeal() for further details.

Exceptions
LockViolationThis triangulation contains at least one locked boundary facet. This exception will be thrown before any changes are made. See Simplex<dim>::lockFacet() for further details on how such locks work and what their implications are.
Returns
true if changes were made, or false if the original triangulation contained no real boundary components.

◆ fourFourMove()

bool regina::Triangulation< 3 >::fourFourMove ( Edge< 3 > * e,
int axis,
bool ignored,
bool perform = true )
inline

Deprecated routine that tests for and optionally performs a 4-4 move about the given edge of this triangulation.

For more details on 4-4 moves and when they can be performed, see move44().

This routine will always check whether the requested move is legal and will not violate any simplex and/or facet locks (see Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on locks). If the move is allowed, and if the argument perform is true, this routine will also perform the move.

Deprecated
If you just wish to test whether such a move is possible, call has44(). If you wish to both check and perform the move, call move44().
Precondition
The given edge is an edge of this triangulation.
Parameters
ethe edge about which to perform the move.
axisindicates which axis of the enclosing octahedron the four new tetrahedra should meet along; this must be 0 or 1. See move44() for details on exactly what this means.
ignoredan argument that is ignored. In earlier versions of Regina this argument controlled whether we check if the move can be performed; however, now this check is done always.
performtrue if we should actually perform the move, assuming the move is allowed.
Returns
true if and only if the requested move could be performed.

◆ fromGluings() [1/2]

Triangulation< dim > regina::detail::TriangulationBase< dim >::fromGluings ( size_t size,
Iterator beginGluings,
Iterator endGluings )
staticinherited

Creates a triangulation from a list of gluings.

This routine is an analogue to the variant of fromGluings() that takes a C++ initialiser list; however, here the input data may be constructed at runtime (which makes it accessible to Python, amongst other things).

The iterator range (beginGluings, endGluings) should encode the list of gluings for the triangulation. Each iterator in this range must dereference to a tuple of the form (simp, facet, adj, gluing); here simp, facet and adj are all integers, and gluing is of type Perm<dim+1>. Each such tuple indicates that facet facet of top-dimensional simplex number simp should be glued to top-dimensional simplex number adj using the permutation gluing. In other words, such a tuple encodes the same information as calling simplex(simp).join(facet, simplex(adj), gluing) upon the triangulation being constructed.

Every gluing should be encoded from one direction only. This means, for example, that to build a closed 3-manifold triangulation with n tetrahedra, you would pass a list of 2n such tuples. If you attempt to make the same gluing twice (e.g., once from each direction), then this routine will throw an exception.

Any facet of a simplex that does not feature in the given list of gluings (either as a source or a destination) will be left as a boundary facet.

Note that, as usual, the top-dimensional simplices are numbered 0,...,(size-1), and the facets of each simplex are numbered 0,...,dim.

As an example, Python users can construct the figure eight knot complement as follows:

tri = Triangulation3.fromGluings(2, [
( 0, 0, 1, Perm4(1,3,0,2) ), ( 0, 1, 1, Perm4(2,0,3,1) ),
( 0, 2, 1, Perm4(0,3,2,1) ), ( 0, 3, 1, Perm4(2,1,0,3) )])
Note
The assumption is that the iterators dereference to a std::tuple<size_t, int, size_t, Perm<dim+1>>. However, this is not strictly necessary - the dereferenced type may be any type that supports std::get (and for which std::get<0..3>() yields suitable integer/permutation types).
Exceptions
InvalidArgumentThe given list of gluings does not correctly describe a triangulation with size top-dimensional simplices.
Python
The gluings should be passed as a single Python list of tuples (not an iterator pair).
Parameters
sizethe number of top-dimensional simplices in the triangulation to construct.
beginGluingsthe beginning of the list of gluings, as described above.
endGluingsa past-the-end iterator indicating the end of the list of gluings.
Returns
the reconstructed triangulation.

◆ fromGluings() [2/2]

Triangulation< dim > regina::detail::TriangulationBase< dim >::fromGluings ( size_t size,
std::initializer_list< std::tuple< size_t, int, size_t, Perm< dim+1 > > > gluings )
inlinestaticinherited

Creates a triangulation from a hard-coded list of gluings.

This routine takes a C++ initialiser list, which makes it useful for creating hard-coded examples directly in C++ code without needing to write a tedious sequence of calls to Simplex<dim>::join().

Each element of the initialiser list should be a tuple of the form (simp, facet, adj, gluing), which indicates that facet facet of top-dimensional simplex number simp should be glued to top-dimensional simplex number adj using the permutation gluing. In other words, such a tuple encodes the same information as calling simplex(simp).join(facet, simplex(adj), gluing) upon the triangulation being constructed.

Every gluing should be encoded from one direction only. This means, for example, that to build a closed 3-manifold triangulation with n tetrahedra, you would pass a list of 2n such tuples. If you attempt to make the same gluing twice (e.g., once from each direction), then this routine will throw an exception.

Any facet of a simplex that does not feature in the given list of gluings (either as a source or a destination) will be left as a boundary facet.

Note that, as usual, the top-dimensional simplices are numbered 0,...,(size-1), and the facets of each simplex are numbered 0,...,dim.

As an example, you can construct the figure eight knot complement using the following code:

{ 0, 0, 1, {1,3,0,2} }, { 0, 1, 1, {2,0,3,1} },
{ 0, 2, 1, {0,3,2,1} }, { 0, 3, 1, {2,1,0,3} }});
A dim-dimensional triangulation, built by gluing together dim-dimensional simplices along their (dim-...
Definition triangulation.h:159
static Triangulation< dim > fromGluings(size_t size, std::initializer_list< std::tuple< size_t, int, size_t, Perm< dim+1 > > > gluings)
Creates a triangulation from a hard-coded list of gluings.
Definition triangulation.h:5465
Note
If you have an existing triangulation that you would like to hard-code in this way, you can call source() to generate the corresponding source code.
Exceptions
InvalidArgumentThe given list of gluings does not correctly describe a triangulation with size top-dimensional simplices.
Python
Not present. Instead, use the variant of fromGluings() that takes this same data using a Python list (which need not be constant).
Parameters
sizethe number of top-dimensional simplices in the triangulation to construct.
gluingsdescribes the gluings between these top-dimensional simplices, as described above.
Returns
the reconstructed triangulation.

◆ fromIsoSig()

static Triangulation< dim > regina::detail::TriangulationBase< dim >::fromIsoSig ( const std::string & sig)
staticinherited

Recovers a full triangulation from an isomorphism signature.

See isoSig() for more information on isomorphism signatures. It will be assumed that the signature describes a triangulation of dimension dim.

Currently this routine only supports isomorphism signatures that were created with the default encoding (i.e., there was no Encoding template parameter passed to isoSig()).

Calling isoSig() followed by fromIsoSig() is not guaranteed to produce an identical triangulation to the original, but it is guaranteed to produce a combinatorially isomorphic triangulation. In other words, fromIsoSig() may reconstruct the triangulation with its simplices and/or vertices relabelled. The optional argument to isoSig() allows you to determine the precise relabelling that will be used, if you need to know it.

For a full and precise description of the isomorphism signature format for 3-manifold triangulations, see Simplification paths in the Pachner graphs of closed orientable 3-manifold triangulations, Burton, 2011, arXiv:1110.6080. The format for other dimensions is essentially the same, but with minor dimension-specific adjustments.

Warning
Do not mix isomorphism signatures between dimensions! It is possible that the same string could corresponding to both a p-dimensional triangulation and a q-dimensional triangulation for different dimensions p and q.
Exceptions
InvalidArgumentThe given string was not a valid dim-dimensional isomorphism signature created using the default encoding.
Parameters
sigthe isomorphism signature of the triangulation to construct. Note that isomorphism signatures are case-sensitive (unlike, for example, dehydration strings for 3-manifolds).
Returns
the reconstructed triangulation.

◆ fromSig()

Triangulation< dim > regina::detail::TriangulationBase< dim >::fromSig ( const std::string & sig)
inlinestaticinherited

Alias for fromIsoSig(), to recover a full triangulation from an isomorphism signature.

This alias fromSig() is provided to assist with generic code that can work with both triangulations and links.

See fromIsoSig() for further details.

Exceptions
InvalidArgumentThe given string was not a valid dim-dimensional isomorphism signature created using the default encoding.
Parameters
sigthe isomorphism signature of the triangulation to construct. Note that isomorphism signatures are case-sensitive (unlike, for example, dehydration strings for 3-manifolds).
Returns
the reconstructed triangulation.

◆ fromSnapPea()

static Triangulation< 3 > regina::Triangulation< 3 >::fromSnapPea ( const std::string & filenameOrContents)
static

Extracts the tetrahedron gluings from the contents of a SnapPea data file.

The argument may be the name of a SnapPea file, or it may also be the contents of a SnapPea file (so the file itself need not actually exist on the filesystem).

Aside from the tetrahedron gluings, all other SnapPea-specific information (such as peripheral curves, and the manifold name) will be ignored, since Regina's Triangulation<3> class does not track such information itself.

If you wish to preserve all SnapPea-specific information from the data file, you should work with the SnapPeaTriangulation class instead (which uses the SnapPea kernel directly, and can therefore store anything that SnapPea can).

One reason for working with this function as opposed to using SnapPeaTriangulation is if you need to preserve the specific triangulation. For example, if the SnapPea data file describes a closed triangulation (where all vertices are finite), then the SnapPea kernel will convert this into an ideal triangulation with filling coefficients, whereas this routine will return the original closed triangulation.

Warning
This routine is "lossy", in that drops SnapPea-specific information (as described above). Unless you specifically need an Triangulation<3> (not an SnapPeaTriangulation) or you need to avoid calling routines from the SnapPea kernel, it is highly recommended that you create a SnapPeaTriangulation from the given file contents instead. See the string-based SnapPeaTriangulation constructor for how to do this.
If (for some reason) you pass a filename that begins with "% Triangulation", then Regina will interpret this as the contents of a SnapPea file (not a filename).
Internationalisation
If the given argument is a filename, then this routine makes no assumptions about the character encoding used in the filename, and simply passes it through unchanged to low-level C/C++ file I/O routines. This routine assumes that the file contents, however, are in UTF-8 (the standard encoding used throughout Regina).
Exceptions
InvalidArgumentThe given string does not provide either the filename or contents of a correctly formatted SnapPea data file.
FileErrorAn error occurred with file I/O (such as testing whether the given file exists, or reading its contents).
Parameters
filenameOrContentseither the name of a SnapPea data file, or the full contents of a SnapPea data file (which need not actually exist on the filesystem).
Returns
a native Regina triangulation extracted from the given SnapPea data.

◆ fundamentalGroup()

const GroupPresentation & regina::detail::TriangulationBase< dim >::fundamentalGroup ( ) const
inlineinherited

An alias for group(), which returns the fundamental group of this triangulation.

See group() for further details, including how ideal vertices and invalid faces are managed.

Note
In Regina 7.2, the routine fundamentalGroup() was renamed to group() for brevity and for consistency with Link::group(). This more expressive name fundamentalGroup() will be kept as a long-term alias, and you are welcome to continue using it if you prefer.
Precondition
This triangulation has at most one component.
Warning
In dimension 3, if you are calling this from the subclass SnapPeaTriangulation then any fillings on the cusps will be ignored. (This is the same as for every routine implemented by Regina's Triangulation<3> class.) If you wish to compute the fundamental group with fillings, call SnapPeaTriangulation::fundamentalGroupFilled() instead.
Returns
the fundamental group.

◆ fVector()

std::vector< size_t > regina::detail::TriangulationBase< dim >::fVector ( ) const
inlineinherited

Returns the f-vector of this triangulation, which counts the number of faces of all dimensions.

The vector that is returned will have length dim+1. If this vector is f, then f[k] will be the number of k-faces for each 0 ≤ k ≤ dim.

This routine is significantly more heavyweight than countFaces(). Its advantage is that, unlike the templatised countFaces(), it allows you to count faces whose dimensions are not known until runtime.

Returns
the f-vector of this triangulation.

◆ generalAngleStructure()

const AngleStructure & regina::Triangulation< 3 >::generalAngleStructure ( ) const
inline

Returns a generalised angle structure on this triangulation, if one exists.

A generalised angle structure must satisfy the same matching equations as all angle structures do, but there is no constraint on the signs of the angles; in particular, negative angles are allowed. If a generalised angle structure does exist, then this routine is guaranteed to return one.

This routine is designed for scenarios where you already know that a generalised angle structure exists. This means:

  • If no generalised angle structure exists, this routine will throw an exception, which will incur a significant overhead.
  • It should be rare that you do not know in advance whether a generalised angle structure exists (see the simple conditions in the note below). However, if you don't yet know, you should call hasGeneralAngleStructure() first. If the answer is no, this will avoid the overhead of throwing and catching exceptions. If the answer is yes, this will have the side-effect of caching the angle structure, which means your subsequent call to generalAngleStructure() will be essentially instantaneous.

The underlying algorithm simply solves a system of linear equations, and so should be fast even for large triangulations.

The result of this routine is cached internally: as long as the triangulation does not change, multiple calls to generalAngleStructure() will return identical angle structures, and every call after the first be essentially instantaneous.

If the triangulation does change, however, then the cached angle structure will be deleted, and any reference that was returned before will become invalid.

As of Regina 7.4, this routine has changed its behaviour for the empty triangulation: it now returns the empty angle structure.

Note
For a valid triangulation with no boundary faces, a generalised angle structure exists if and only if every vertex link is a torus or Klein bottle. The "only if" direction is a simple Euler characteristic calculation; for the "if" direction see "Angle structures and normal surfaces", Feng Luo and Stephan Tillmann, Trans. Amer. Math. Soc. 360:6 (2008), pp. 2849-2866).
Exceptions
NoSolutionNo generalised angle structure exists on this triangulation.
Returns
a generalised angle structure on this triangulation, if one exists.

◆ group()

const GroupPresentation & regina::detail::TriangulationBase< dim >::group ( ) const
inherited

Returns the fundamental group of this triangulation.

The fundamental group is computed in the dual 2-skeleton. This means:

  • If the triangulation contains any ideal vertices, the fundamental group will be calculated as if each such vertex had been truncated.
  • Likewise, if the triangulation contains any invalid faces of dimension 0,1,...,(dim-3), these will effectively be truncated also.
  • In contrast, if the triangulation contains any invalid (dim-2)-faces (i.e., codimension-2-faces that are identified with themselves under a non-trivial map), the fundamental group will be computed without truncating the centroid of the face. For instance, if a 3-manifold triangulation has an edge identified with itself in reverse, then the fundamental group will be computed without truncating the resulting projective plane cusp. This means that, if a barycentric subdivision is performed on a such a triangulation, the result of group() might change.

Bear in mind that each time the triangulation changes, the fundamental group will be deleted. Thus the reference that is returned from this routine should not be kept for later use. Instead, group() should be called again; this will be instantaneous if the group has already been calculated.

Before Regina 7.2, this routine was called fundamentalGroup(). It has since been renamed to group() for brevity and for consistency with Link::group(). The more expressive name fundamentalGroup() will be kept, and you are welcome to use that instead if you prefer.

Precondition
This triangulation has at most one component.
Warning
In dimension 3, if you are calling this from the subclass SnapPeaTriangulation then any fillings on the cusps will be ignored. (This is the same as for every routine implemented by Regina's Triangulation<3> class.) If you wish to compute the fundamental group with fillings, call SnapPeaTriangulation::fundamentalGroupFilled() instead.
Returns
the fundamental group.

◆ has02() [1/3]

bool regina::Triangulation< 3 >::has02 ( Edge< 3 > * e,
size_t t0,
size_t t1 ) const
inline

Determines whether it is possible to perform a 0-2 move about the two specified triangles of this triangulation, without violating any facet locks.

For more detail on 0-2 moves and when they can be performed, and for full details on what the arguments to this function mean, see move02(Edge<3>*, size_t, size_t).

Precondition
The given edge is a edge of this triangulation.
Parameters
ethe common edge of the two candidate triangles about which to perform the move.
t0the number assigned to one of two candidate triangles about which to perform the move.
t1the number assigned to the other candidate triangle about which to perform the move.
Returns
true if and only if the requested move can be performed.
Author
Alex He

◆ has02() [2/3]

bool regina::Triangulation< 3 >::has02 ( EdgeEmbedding< 3 > e0,
int t0,
EdgeEmbedding< 3 > e1,
int t1 ) const
inline

Determines whether it is possible to perform a 0-2 move about the two specified triangles of this triangulation, without violating any facet locks.

For more detail on 0-2 moves and when they can be performed, and for full details on what the arguments to this function mean, see move02(EdgeEmbedding<3>, int, EdgeEmbedding<3>, int).

Precondition
The given embeddings refer to edges of this triangulation.
Parameters
e0an embedding of the common edge e of the two candidate triangles about which to perform the move.
t0indicates one of the candidate triangles about which to perform the move, with respect to the edge embedding e0; this must be 2 or 3.
e1another embedding of the edge e.
t1indicates the other candidate triangle about which to perform the move, with respect to the edge embedding e1; this must be 2 or 3.
Returns
true if and only if the requested move can be performed.
Author
Alex He

◆ has02() [3/3]

bool regina::Triangulation< 3 >::has02 ( Triangle< 3 > * t0,
int e0,
Triangle< 3 > * t1,
int e1 ) const
inline

Determines whether it is possible to perform a 0-2 move about the two given triangles of this triangulation, without violating any facet locks.

For more detail on 0-2 moves and when they can be performed, and for full details on what the arguments to this function mean, see move02(Triangle<3>*, int, Triangle<3>*, int).

Precondition
The given triangles are both triangles of this triangulation.
Parameters
t0one of the two candidate triangles about which to perform the move.
e0the edge at which t0 meets the other triangle t1; this must be 0, 1 or 2.
t1the other candidate triangle about which to perform the move.
e1the edge at which t1 meets the other triangle t0; this must be 0, 1 or 2.
Returns
true if and only if the requested move can be performed.
Author
Alex He

◆ has20()

bool regina::detail::TriangulationBase< dim >::has20 ( Face< dim, k > * f) const
inherited

Determines whether it is possible to perform a 2-0 move about the given k-face of this triangulation, without violating any simplex and/or facet locks.

For more detail on 2-0 moves and when they can be performed, see move20().

Precondition
The given k-face is a k-face of this triangulation.
Template Parameters
kthe dimension of the given face. This must be 0, 1 or 2, and must not exceed dim - 2.
Parameters
fthe k-face about which to perform the candidate move.
Returns
true if and only if the requested move can be performed.

◆ has21()

bool regina::Triangulation< 3 >::has21 ( Edge< 3 > * e,
int edgeEnd ) const
inline

Determines whether it is possible to perform a 2-1 move at the given end of the given edge of this triangulation, without violating any simplex and/or facet locks.

For more detail on 2-1 moves and when they can be performed, see move21().

Precondition
The given edge is a edge of this triangulation.
Parameters
ethe candidate edge about which to perform the move.
edgeEndindicates at which end of the edge e the move does not involve the adjacent tetrahedron; this should be 0 or 1. See move21() for details on exactly what this means.
Returns
true if and only if the requested move can be performed.

◆ has44()

bool regina::Triangulation< 3 >::has44 ( Edge< 3 > * e,
int axis ) const
inline

Determines whether it is possible to perform a 4-4 move about the given edge of this triangulation, without violating any simplex and/or facet locks.

For more detail on 4-4 moves and when they can be performed, see move44().

Precondition
The given edge is a edge of this triangulation.
Parameters
ethe candidate edge about which to perform the move.
axisindicates which axis of the enclosing octahedron the four new proposed tetrahedra should meet along; this must be 0 or 1. See move44() for details on exactly what this means.
Returns
true if and only if the requested move can be performed.

◆ hasBoundaryFacets()

bool regina::detail::TriangulationBase< dim >::hasBoundaryFacets ( ) const
inlineinherited

Determines if this triangulation has any boundary facets.

This routine returns true if and only if the triangulation contains some top-dimension simplex with at least one facet that is not glued to an adjacent simplex.

Returns
true if and only if there are boundary facets.

◆ hasBoundaryTriangles()

bool regina::Triangulation< 3 >::hasBoundaryTriangles ( ) const
inline

A dimension-specific alias for hasBoundaryFacets().

See hasBoundaryFacets() for further information.

◆ hasCloseBook()

bool regina::Triangulation< 3 >::hasCloseBook ( Edge< 3 > * e) const
inline

Determines whether it is possible to perform a book closing move about the given edge of this triangulation, without violating any facet locks.

For more detail on book closing moves and when they can be performed, see closeBook().

Precondition
The given edge is an edge of this triangulation.
Parameters
ethe candidate edge about which to perform the move.
Returns
true if and only if the requested move can be performed.

◆ hasCollapseEdge()

bool regina::Triangulation< 3 >::hasCollapseEdge ( Edge< 3 > * e) const
inline

Determines whether it is possible to collapse the given edge of this triangulation, without violating any simplex and/or facet locks.

For more detail on edge collapse moves and when they can be performed, see collapseEdge().

Precondition
The given edge is an edge of this triangulation.
Parameters
ethe candidate edge to collapse.
Returns
true if and only if the requested move can be performed.

◆ hasCompressingDisc()

bool regina::Triangulation< 3 >::hasCompressingDisc ( ) const

Searches for a compressing disc within the underlying 3-manifold.

Let M be the underlying 3-manifold and let B be its boundary. By a compressing disc, we mean a disc D properly embedded in M, where the boundary of D lies in B but does not bound a disc in B.

This routine will first call the heuristic routine hasSimpleCompressingDisc() in the hope of obtaining a fast answer. If this fails, it will do one of two things:

  • If the triangulation is orientable and 1-vertex, it will use the linear programming and crushing machinery outlined in "Computing closed essential surfaces in knot complements", Burton, Coward and Tillmann, SCG '13, p405-414, 2013. This is often extremely fast, even for triangulations with many tetrahedra.
  • If the triangulation is non-orientable or has multiple vertices then it will run a full enumeration of vertex normal surfaces, as described in "Algorithms for the complete decomposition of a closed 3-manifold", Jaco and Tollefson, Illinois J. Math. 39 (1995), 358-406. As the number of tetrahedra grows, this can become extremely slow.

This routine will work on a copy of this triangulation, not the original. In particular, the copy will be simplified, which means that there is no harm in calling this routine on an unsimplified triangulation.

If this triangulation has no boundary components, this routine will simply return false.

Precondition
This triangulation is valid and is not ideal.
The underlying 3-manifold is irreducible.
Warning
This routine can be infeasibly slow for large triangulations (particularly those that are non-orientable or have multiple vertices), since it may need to perform a full enumeration of vertex normal surfaces, and since it might perform "large" operations on these surfaces such as cutting along them. See hasSimpleCompressingDisc() for a "heuristic shortcut" that is faster but might not give a definitive answer.
Returns
true if the underlying 3-manifold contains a compressing disc, or false if it does not.

◆ hasGeneralAngleStructure()

bool regina::Triangulation< 3 >::hasGeneralAngleStructure ( ) const

Determines whether this triangulation supports a generalised angle structure.

A generalised angle structure must satisfy the same matching equations as all angle structures do, but there is no constraint on the signs of the angles; in particular, negative angles are allowed.

This routine returns false if and only if generalAngleStructure() throws an exception. However, if you do not know whether a generalised angle structure exists, then this routine is faster:

  • If there is no generalised angle structure, this routine will avoid the overhead of throwing and catching exceptions.
  • If there is a generalised angle structure, this routine will find and cache this angle structure, which means that any subsequent call to generalAngleStructure() to retrieve its details will be essentially instantaneous.

The underlying algorithm simply solves a system of linear equations, and so should be fast even for large triangulations.

As of Regina 7.4, this routine has changed its behaviour for the empty triangulation: it now returns true, and caches the empty angle structure as its solution.

Note
For a valid triangulation with no boundary faces, a generalised angle structure exists if and only if every vertex link is a torus or Klein bottle. The "only if" direction is a simple Euler characteristic calculation; for the "if" direction see "Angle structures and normal surfaces", Feng Luo and Stephan Tillmann, Trans. Amer. Math. Soc. 360:6 (2008), pp. 2849-2866).
Even if the condition above is true and it is clear that a generalised angle structure should exist, this routine will still do the extra work to compute an explicit solution (in order to fulfil the promise made in the generalAngleStructure() documentation).
Returns
true if and only if a generalised angle structure exists on this triangulation.

◆ hash()

size_t regina::TightEncodable< Triangulation< dim > >::hash ( ) const
inlineinherited

Hashes this object to a non-negative integer, allowing it to be used for keys in hash tables.

This hash function makes use of Regina's tight encodings. In particular, any two objects with the same tight encoding will have equal hashes. This implementation (and therefore the specific hash value for each object) is subject to change in future versions of Regina.

Python
For Python users, this function uses the standard Python name hash(). This allows objects of this type to be used as keys in Python dictionaries and sets.
Returns
The integer hash of this object.

◆ hasLocks()

bool regina::detail::TriangulationBase< dim >::hasLocks ( ) const
inherited

Identifies whether any top-dimensional simplices and/or any of their facets are locked.

In short, locking a top-dimensional simplex and/or some of its facets means that that the simplex and/or facets must not be changed. See Simplex<dim>::lock() and Simplex<dim>::lockFacet() for full details on how locks work and what their implications are.

Returns
true if and only if there is at least one locked top-dimensional simplex or at least one locked facet of a top-dimensional simplex within this triangulation.

◆ hasMinimalBoundary()

bool regina::Triangulation< 3 >::hasMinimalBoundary ( ) const

Determines whether the boundary of this triangulation contains the smallest possible number of triangles.

This is true if and only if, amongst all real boundary components, every sphere or projective plane boundary component has precisely two triangles, and every other boundary component has precisely one vertex.

For the purposes of this routine, ideal boundary components are ignored.

If this routine returns false, you can call minimiseBoundary() to make the number of boundary triangles minimal.

Precondition
This triangulation is valid.
Returns
true if and only if the boundary contains the smallest possible number of triangles.

◆ hasMinimalVertices()

bool regina::Triangulation< 3 >::hasMinimalVertices ( ) const

Determines whether this triangulation contains the smallest possible number of vertices for the 3-manifold that it represents.

This is true if and only if:

  • amongst all real boundary components, every sphere or projective plane boundary component has precisely two triangles, and every other boundary component has precisely one vertex;
  • amongst all connected components, every closed component has precisely one vertex, and every component with real or ideal boundary has no internal vertices at all.

If this routine returns false, you can call minimiseVertices() to make the number of vertices minimal.

Precondition
This triangulation is valid.
Returns
true if and only if this triangulation contains the smallest possible number of vertices.

◆ hasNegativeIdealBoundaryComponents()

bool regina::Triangulation< 3 >::hasNegativeIdealBoundaryComponents ( ) const
inline

Determines if this triangulation contains any ideal boundary components with negative Euler characteristic.

Returns
true if and only if there is at least one such boundary component.

◆ hasOpenBook()

bool regina::Triangulation< 3 >::hasOpenBook ( Triangle< 3 > * t) const
inline

Determines whether it is possible to perform a book opening move about the given triangle of this triangulation, without violating any facet locks.

For more detail on book opening moves and when they can be performed, see openBook().

Precondition
The given triangle is a triangle of this triangulation.
Parameters
tthe candidate triangle about which to perform the move.
Returns
true if and only if the requested move can be performed.

◆ hasPachner()

bool regina::detail::TriangulationBase< dim >::hasPachner ( Face< dim, k > * f) const
inherited

Determines whether it is possible to perform a (dim + 1 - k)-(k + 1) Pachner move about the given k-face of this triangulation, without violating any simplex and/or facet locks.

For more detail on Pachner moves and when they can be performed, see pachner().

Precondition
The given k-face is a k-face of this triangulation.
Template Parameters
kthe dimension of the given face. This must be between 0 and (dim) inclusive.
Parameters
fthe k-face about which to perform the candidate move.
Returns
true if and only if the requested move can be performed.

◆ hasShellBoundary()

bool regina::detail::TriangulationBase< dim >::hasShellBoundary ( Simplex< dim > * s) const
inherited

Determines whether it is possible to perform a boundary shelling move upon the given top-dimensional simplex of this triangulation, without violating any simplex and/or facet locks.

This test is only available in standard dimensions, since Regina's notion of "valid faces" is weaker in higher dimensions (due to the need to solve undecidable problems). See Face::isValid() for further discussion.

For more detail on boundary shelling moves and when they can be performed, see shellBoundary().

Precondition
The dimension dim is one of Regina's standard dimensions.
The given simplex is a simplex of this triangulation.
Parameters
sthe top-dimensional simplex upon which to perform the candidate move.
Returns
true if and only if the requested move can be performed.

◆ hasSimpleCompressingDisc()

bool regina::Triangulation< 3 >::hasSimpleCompressingDisc ( ) const

Searches for a "simple" compressing disc inside this triangulation.

Let M be the underlying 3-manifold and let B be its boundary. By a compressing disc, we mean a disc D properly embedded in M, where the boundary of D lies in B but does not bound a disc in B.

By a simple compressing disc, we mean a compressing disc that has a very simple combinatorial structure (here "simple" is subject to change; see the warning below). Examples include the compressing disc inside a 1-tetrahedron solid torus, or a compressing disc formed from a single internal triangle surrounded by three boundary edges.

The purpose of this routine is to avoid working with normal surfaces within a large triangulation where possible. This routine is relatively fast, and if it returns true then this 3-manifold definitely contains a compressing disc. If this routine returns false then there might or might not be a compressing disc; the user will need to perform a full normal surface enumeration using hasCompressingDisc() to be sure.

This routine will work on a copy of this triangulation, not the original. In particular, the copy will be simplified, which means that there is no harm in calling this routine on an unsimplified triangulation.

If this triangulation has no boundary components, this routine will simply return false.

For further information on this test, see "The Weber-Seifert dodecahedral space is non-Haken", Benjamin A. Burton, J. Hyam Rubinstein and Stephan Tillmann, Trans. Amer. Math. Soc. 364:2 (2012), pp. 911-932.

Warning
The definition of "simple" is subject to change in future releases of Regina. That is, this routine may be expanded over time to identify more types of compressing discs (thus making it more useful as a "heuristic shortcut").
Precondition
This triangulation is valid and is not ideal.
Returns
true if a simple compressing disc was found, or false if not. Note that even with a return value of false, there might still be a compressing disc (just not one with a simple combinatorial structure).

◆ hasSplittingSurface()

bool regina::Triangulation< 3 >::hasSplittingSurface ( ) const

Determines whether this triangulation has a normal splitting surface.

See NormalSurface::isSplitting() for details regarding normal splitting surfaces.

In the special case where this is the empty triangulation, this routine returns false.

As of Regina 6.0, this routine is now fast (small polynomial time), and works even for triangulations with more than one connected component. Thanks to Robert Haraway.

Returns
true if and only if this triangulation has a normal splitting surface.

◆ hasStrictAngleStructure()

bool regina::Triangulation< 3 >::hasStrictAngleStructure ( ) const

Determines whether this triangulation supports a strict angle structure.

Recall that a strict angle structure is one in which every angle is strictly between 0 and π.

This routine returns false if and only if strictAngleStructure() throws an exception. However, if you do not know whether a strict angle structure exists, then this routine is faster:

  • If there is no strict angle structure, this routine will avoid the overhead of throwing and catching exceptions.
  • If there is a strict angle structure, this routine will find and cache this angle structure, which means that any subsequent call to strictAngleStructure() to retrieve its details will be essentially instantaneous.

The underlying algorithm runs a single linear program (it does not enumerate all vertex angle structures). This means that it is likely to be fast even for large triangulations.

As of Regina 7.4, this routine has changed its behaviour for the empty triangulation: it now returns true, since the empty angle structure is (strictly speaking) both strict and taut.

Returns
true if and only if a strict angle structure exists on this triangulation.

◆ hasTwoSphereBoundaryComponents()

bool regina::Triangulation< 3 >::hasTwoSphereBoundaryComponents ( ) const
inline

Determines if this triangulation contains any two-sphere boundary components.

Returns
true if and only if there is at least one two-sphere boundary component.

◆ homology() [1/2]

AbelianGroup regina::detail::TriangulationBase< dim >::homology ( ) const
inherited

Returns the kth homology group of this triangulation, treating any ideal vertices as though they had been truncated.

For C++ programmers who know subdim at compile time, you should use this template function homology<subdim>(), which is slightly faster than passing subdim as an ordinary runtime argument to homology(subdim).

See the non-templated homology(int) for full details on exactly what this function computes.

Precondition
Unless you are computing first homology (k = 1), this triangulation must be valid, and every face that is not a vertex must have a ball or sphere link. The link condition already forms part of the validity test if dim is one of Regina's standard dimensions, but in higher dimensions it is the user's own responsibility to ensure this. See isValid() for details.
Exceptions
FailedPreconditionThis triangulation is invalid, and the homology dimension k is not 1.
Python
Not present. Instead use the variant homology(k).
Template Parameters
kthe dimension of the homology group to return; this must be between 1 and (dim - 1) inclusive if dim is one of Regina's standard dimensions, or between 1 and (dim - 2) inclusive if not.
Returns
the kth homology group.

◆ homology() [2/2]

AbelianGroup regina::detail::TriangulationBase< dim >::homology ( int k) const
inlineinherited

Returns the kth homology group of this triangulation, treating any ideal vertices as though they had been truncated, where the parameter k does not need to be known until runtime.

For C++ programmers who know k at compile time, you are better off using the template function homology<k>() instead, which is slightly faster.

A problem with computing homology is that, if dim is not one of Regina's standard dimensions, then Regina cannot actually detect ideal vertices (since in general this requires solving undecidable problems). Currently we resolve this by insisting that, in higher dimensions, the homology dimension k is at most (dim-2); the underlying algorithm will then effectively truncate all vertices (since truncating "ordinary" vertices whose links are spheres or balls does not affect the kth homology in such cases).

In general, this routine insists on working with a valid triangulation (see isValid() for what this means). However, for historical reasons, if you are computing first homology (k = 1) then your triangulation is allowed to be invalid, though the results might or might not be useful to you. The homology will be computed using the dual skeleton: what this means is that any invalid faces of dimension 0,1,...,(dim-3) will be treated as though their centroids had been truncated, but any invalid (dim-2)-faces will be treated without such truncation. A side-effect is that, after performing a barycentric on an invalid triangulation, the group returned by homology<1>() might change.

Warning
In dimension 3, if you are calling this from the subclass SnapPeaTriangulation then any fillings on the cusps will be ignored. (This is the same as for every routine implemented by Regina's Triangulation<3> class.) If you wish to compute homology with fillings, call SnapPeaTriangulation::homologyFilled() instead.
Precondition
Unless you are computing first homology (k = 1), this triangulation must be valid, and every face that is not a vertex must have a ball or sphere link. The link condition already forms part of the validity test if dim is one of Regina's standard dimensions, but in higher dimensions it is the user's own responsibility to ensure this. See isValid() for details.
Exceptions
FailedPreconditionThis triangulation is invalid, and the homology dimension k is not 1.
InvalidArgumentThe homology dimension k is outside the supported range. This range depends upon the triangulation dimension dim; for details see the documentation below for the argument k.
Python
Like the C++ template function homology<k>(), you can omit the homology dimension k; this will default to 1.
Parameters
kthe dimension of the homology group to return; this must be between 1 and (dim - 1) inclusive if dim is one of Regina's standard dimensions, or between 1 and (dim - 2) inclusive if not.
Returns
the kth homology group.

◆ homologyBdry()

const AbelianGroup & regina::Triangulation< 3 >::homologyBdry ( ) const

Returns the first homology group of the boundary for this triangulation.

Note that ideal vertices are considered part of the boundary.

Bear in mind that each time the triangulation changes, the homology groups will be deleted. Thus the reference that is returned from this routine should not be kept for later use. Instead, homologyBdry() should be called again; this will be instantaneous if the group has already been calculated.

This routine is fairly fast, since it deduces the homology of each boundary component through knowing what kind of surface it is.

Precondition
This triangulation is valid.
Exceptions
FailedPreconditionThis triangulation is invalid.
Returns
the first homology group of the boundary.

◆ homologyH2Z2()

unsigned long regina::Triangulation< 3 >::homologyH2Z2 ( ) const
inline

Returns the second homology group with coefficients in Z_2 for this triangulation.

If this triangulation contains any ideal vertices, the homology group will be calculated as if each such vertex had been truncated. The algorithm used calculates the relative first homology group with respect to the boundary and uses homology and cohomology theorems to deduce the second homology group.

This group will simply be the direct sum of several copies of Z_2, so the number of Z_2 terms is returned.

Precondition
This triangulation is valid.
Exceptions
FailedPreconditionThis triangulation is invalid.
Returns
the number of Z_2 terms in the second homology group with coefficients in Z_2.

◆ homologyRel()

const AbelianGroup & regina::Triangulation< 3 >::homologyRel ( ) const

Returns the relative first homology group with respect to the boundary for this triangulation.

Note that ideal vertices are considered part of the boundary.

Bear in mind that each time the triangulation changes, the homology groups will be deleted. Thus the reference that is returned from this routine should not be kept for later use. Instead, homologyRel() should be called again; this will be instantaneous if the group has already been calculated.

Precondition
This triangulation is valid.
Exceptions
FailedPreconditionThis triangulation is invalid.
Returns
the relative first homology group with respect to the boundary.

◆ idealToFinite()

bool regina::Triangulation< 3 >::idealToFinite ( )
inline

Alias for truncateIdeal(), which truncates all ideal or invalid vertices to convert these into real boundary components.

This alias idealToFinite() is provided for compatibility with older versions of Regina. (It is not deprecated, and so this alias should remain part of Regina for a long time.)

See truncateIdeal() for further details.

Exceptions
LockViolationThis triangulation contains at least one locked top-dimensional simplex and/or facet. This exception will be thrown before any changes are made. See Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on how such locks work and what their implications are.
Returns
true if and only if the triangulation was changed.

◆ improveTreewidth()

bool regina::Triangulation< 3 >::improveTreewidth ( ssize_t maxAttempts = 5000,
int height = 2,
int threads = 1,
ProgressTrackerOpen * tracker = nullptr )

Attempts to retriangulate this to have a smaller width tree decomposition.

Regina does not compute treewidth precisely (and indeed, this is an NP-hard problem); instead what it tries to minimise is the width of the greedy tree decomposition produced by TreeDecomposition(triangulation).

Much like simplifyExhaustive(), this routine searches for a better triangulation by performing an exhaustive search through all triangulations that can be reached from this via 2-3 and 3-2 Pachner moves, within certain user-supplied limits as described below.

This routine can be very slow and very memory-intensive: the number of triangulations it visits may be superexponential in the number of tetrahedra, and it records every triangulation that it visits (so as to avoid revisiting the same triangulation again). You can limit the cost of this search in two ways:

  • You can pass a maxAttempts argument, which means this return will give up after visiting maxAttempts distinct triangulations (up to the kind of combinatorial equivalence described by sig()). If maxAttempts is negative, the number of attempts will not be limited.
  • You can pass a height argument to limit the number of extra tetrahedra. Again, if height is negative, the number of additional tetrahedra will not be limited.
  • The defaults for maxAttempts and height are both non-negative, and have been chosen to keep the default invocation of this routine relatively fast.
  • If both maxAttempts and height are negative, this routine will not terminate until a smaller-width triangulation is found (unless there are so many locks that the number of reachable triangulations is finite). This means that, if no such triangulation exists, the only way to terminate this routine is to cancel the operation via a progress tracker (read on for details).

If this triangulation is currently oriented, then this operation will not preserve the orientation: indeed, the resulting triangulation might not be oriented at all. Like simplifyExhaustive(), this is a consequence of the way in which this operation uses isomorphism signatures to represent nodes in the Pachner graph.

If any tetrahedra and/or triangles are locked, these locks will be respected: that is, the retriangulation will avoid any moves that would violate these locks (and in particular, no LockViolation exceptions should be thrown). Of course, however, having locks may reduce the number of distinct triangulations that can be reached.

If this routine finds a triangulation with a smaller-width greedy tree decomposition, then:

  • If maxAttempts was negative (i.e., unlimited), it will stop the search at this point and leave you with this better triangulation. You may wish to try calling improveTreewidth() again, since it is possible that another search will be able to improve the triangulation even further.
  • If maxAttempts was non-negative (i.e., limited), it will keep going by restarting the search again from this better triangulation. In other words, this routine will proceed with a kind of "greedy descent". The height argument will now be treated with respect to this new triangulation, and the number of attempts (which is limited by maxAttempts) will be reset to zero. This means that overall you may end up with more than height extra tetrahedra, and you may have visited more than maxAttempts distinct triangulations; however, if this happens then you know you are getting a better triangulation.

If this routine cannot produce a smaller-width tree decomposition within the bounds given via maxAttempts and/or height, then it will leave this triangulation unchanged.

To assist with performance, this routine can run in parallel (multithreaded) mode; simply pass the number of parallel threads in the argument threads. Even in multithreaded mode, this routine will not return until processing has finished (i.e., either a better triangulation was found or the search was exhausted), and any change to this triangulation will happen in the calling thread.

Precondition
This triangulation is connected.
Exceptions
FailedPreconditionThis triangulation has more than one connected component. If a progress tracker was passed, it will be marked as finished before the exception is thrown.
Python
The global interpreter lock will be released while this function runs, so you can use it with Python-based multithreading.
Parameters
maxAttemptsthe maximum number of distinct triangulations to examine before we give up and return false, or a negative number if this should not be bounded.
heightthe maximum number of additional tetrahedra to allow, or a negative number if this should not be bounded.
threadsthe number of threads to use. If this is 1 or smaller then the routine will run single-threaded.
trackera progress tracker through which progress will be reported, or null if no progress reporting is required.
Returns
true if and only if this triangulation was successfully changed to give a smaller-width greedy tree decomposition.

◆ inAnyPacket() [1/2]

std::shared_ptr< Packet > regina::Triangulation< 3 >::inAnyPacket ( )

Returns the packet that holds this data, even if it is held indirectly via a SnapPea triangulation.

This routine is similar to PacketOf<Triangulation<3>>::packet(). In particular, if this triangulation is held directly by a 3-dimensional triangulation packet p, then this routine will return p.

The difference is when this triangulation is held "indirectly" by a SnapPea triangulation packet q (i.e., this is the inherited Triangulation<3> data belonging to the SnapPea triangulation). In such a scenario, Triangulation<3>::packet() will return null (since there is no "direct" 3-dimensional triangulation packet), but inAnyPacket() will return q (since the triangulation is still "indirectly" held by a different type of packet).

Returns
the packet that holds this data (directly or indirectly), or null if this data is not held by either a 3-dimensional triangulation packet or a SnapPea triangulation packet.

◆ inAnyPacket() [2/2]

std::shared_ptr< const Packet > regina::Triangulation< 3 >::inAnyPacket ( ) const

Returns the packet that holds this data, even if it is held indirectly via a SnapPea triangulation.

This routine is similar to PacketOf<Triangulation<3>>::packet(). In particular, if this triangulation is held directly by a 3-dimensional triangulation packet p, then this routine will return p.

The difference is when this triangulation is held "indirectly" by a SnapPea triangulation packet q (i.e., this is the inherited Triangulation<3> data belonging to the SnapPea triangulation). In such a scenario, Triangulation<3>::packet() will return null (since there is no "direct" 3-dimensional triangulation packet), but inAnyPacket() will return q (since the triangulation is still "indirectly" held by a different type of packet).

Returns
the packet that holds this data (directly or indirectly), or null if this data is not held by either a 3-dimensional triangulation packet or a SnapPea triangulation packet.

◆ insertLayeredSolidTorus()

Tetrahedron< 3 > * regina::Triangulation< 3 >::insertLayeredSolidTorus ( size_t cuts0,
size_t cuts1 )

Inserts a new layered solid torus into the triangulation.

The meridinal disc of the layered solid torus will intersect the three edges of the boundary torus in cuts0, cuts1 and (cuts0 + cuts1) points respectively.

The boundary torus will always consist of faces 012 and 013 of the tetrahedron containing this boundary torus (this tetrahedron will be returned). In face 012, edges 12, 02 and 01 will meet the meridinal disc cuts0, cuts1 and (cuts0 + cuts1) times respectively. The only exceptions are if these three intersection numbers are (1,1,2) or (0,1,1), in which case edges 12, 02 and 01 will meet the meridinal disc (1, 2 and 1) or (1, 1 and 0) times respectively.

The new tetrahedra will be inserted at the end of the list of tetrahedra in the triangulation.

Precondition
0 ≤ cuts0 ≤ cuts1;
gcd(cuts0, cuts1) = 1.
Exceptions
InvalidArgumentThe preconditions above do not hold; that is, either cuts0 > cuts1, and/or cuts0 and cuts1 are not coprime.
Parameters
cuts0the smallest of the three desired intersection numbers.
cuts1the second smallest of the three desired intersection numbers.
Returns
the tetrahedron containing the boundary torus.
See also
LayeredSolidTorus

◆ insertTriangulation() [1/2]

void regina::detail::TriangulationBase< dim >::insertTriangulation ( const Triangulation< dim > & source)
inherited

Inserts a copy of the given triangulation into this triangulation.

The top-dimensional simplices of source will be copied into this triangulation, and placed after any pre-existing simplices. Specifically, if the original size of this triangulation was N, then source.simplex(i) will be copied to a new simplex which will appear as simplex(N+i) of this triangulation.

The copies will use the same vertex numbering and descriptions as the original simplices from source, and any gluings between the simplices of source will likewise be copied across as gluings between their copies in this triangulation.

As a trivial consequence, if this and the given triangulation are both oriented, then the result will preserve these orientations.

If source has locks on any top-dimensional simplices and/or their facets, these locks will also be copied over to this triangulation.

This routine behaves correctly when source is this triangulation.

Parameters
sourcethe triangulation whose copy will be inserted.

◆ insertTriangulation() [2/2]

void regina::detail::TriangulationBase< dim >::insertTriangulation ( Triangulation< dim > && source)
inherited

Moves the contents of the given triangulation into this triangulation.

The top-dimensional simplices of source will be moved directly into this triangulation, and placed after any pre-existing simplices. Specifically, if the original size of this triangulation was N, then source.simplex(i) will become simplex(N+i) of this triangulation.

As is normal for an rvalue reference, after calling this function source will be unusable. Any simplex pointers that referred to either this triangulation or source will remain valid (and will all now refer to this triangulation), though if they originally referred to source then they will now return different indices. Any locks on top-dimensional simplices and/or their facets will be preserved.

Calling tri.insertTriangulation(source) (where source is an rvalue reference) is similar to calling source.moveContentsTo(tri), but it is a little faster since it does not need to leave source in a usable state.

Regarding packet change events: this function does not fire a change event on source, since it assumes that source is about to be destroyed (which will fire a destruction event instead).

Precondition
source is not this triangulation.
Python
Not present. Only the copying version of this function is available (i.e., the version that takes source as a const reference). If you want a fast move operation, call source.moveContentsTo(this).
Parameters
sourcethe triangulation whose contents should be moved.

◆ intelligentSimplify()

bool regina::Triangulation< 3 >::intelligentSimplify ( )
inline

Deprecated alias for simplify(), which attempts to simplify this triangulation as intelligently as possible using fast and greedy heuristics.

Deprecated
This routine has been renamed to simplify(). See simplify() for further details.
Returns
true if and only if the triangulation was successfully simplified. Otherwise this triangulation will not be changed.

◆ isBall()

bool regina::Triangulation< 3 >::isBall ( ) const

Determines whether this is a triangulation of a 3-dimensional ball.

This routine is based on isSphere(), which in turn combines Rubinstein's 3-sphere recognition algorithm with Jaco and Rubinstein's 0-efficiency prime decomposition algorithm.

Warning
The algorithms used in this routine rely on normal surface theory and so can be very slow for larger triangulations (although faster tests are used where possible). The routine knowsBall() can be called to see if this property is already known or if it happens to be very fast to calculate for this triangulation.
Returns
true if and only if this is a triangulation of a 3-dimensional ball.

◆ isClosed()

bool regina::Triangulation< 3 >::isClosed ( ) const
inline

Determines if this triangulation is closed.

This is the case if and only if it has no boundary. Note that ideal triangulations are not closed.

Returns
true if and only if this triangulation is closed.

◆ isConnected()

bool regina::detail::TriangulationBase< dim >::isConnected ( ) const
inlineinherited

Determines if this triangulation is connected.

This routine returns false only if there is more than one connected component. In particular, it returns true for the empty triangulation.

Returns
true if and only if this triangulation is connected.

◆ isContainedIn()

std::optional< Isomorphism< dim > > regina::detail::TriangulationBase< dim >::isContainedIn ( const Triangulation< dim > & other) const
inlineinherited

Determines if an isomorphic copy of this triangulation is contained within the given triangulation, possibly as a subcomplex of some larger component (or components).

Specifically, this routine determines if there is a boundary incomplete combinatorial isomorphism from this triangulation to other. Boundary incomplete isomorphisms are described in detail in the Isomorphism class notes.

In particular, note that facets of top-dimensional simplices that lie on the boundary of this triangulation need not correspond to boundary facets of other, and that other may contain more top-dimensional simplices than this triangulation.

Like isIsomorphicTo() and the equality test, this routine does not examine or compare simplex/facet locks.

If a boundary incomplete isomorphism is found, the details of this isomorphism are returned. Thus, to test whether an isomorphism exists, you can just call if (isContainedIn(other)).

If more than one such isomorphism exists, only one will be returned. For a routine that returns all such isomorphisms, see findAllSubcomplexesIn().

Warning
For large dimensions, this routine can become extremely slow: its running time includes a factor of (dim+1)!.
Parameters
otherthe triangulation in which to search for an isomorphic copy of this triangulation.
Returns
details of the isomorphism if such a copy is found, or no value otherwise.

◆ isEmpty()

bool regina::detail::TriangulationBase< dim >::isEmpty ( ) const
inlineinherited

Determines whether this triangulation is empty.

An empty triangulation is one with no simplices at all.

Returns
true if and only if this triangulation is empty.

◆ isHaken()

bool regina::Triangulation< 3 >::isHaken ( ) const

Determines whether the underlying 3-manifold (which must be closed and orientable) is Haken.

In other words, this routine determines whether the underlying 3-manifold contains an embedded closed two-sided incompressible surface.

Currently Hakenness testing is available only for irreducible manifolds. This routine will first test whether the manifold is irreducible and, if it is not, will return false immediately.

Precondition
This triangulation is valid, closed, orientable and connected.
Warning
This routine could be very slow for larger triangulations.
Returns
true if and only if the underlying 3-manifold is irreducible and Haken.

◆ isIdeal()

bool regina::Triangulation< 3 >::isIdeal ( ) const
inline

Determines if this triangulation is ideal.

This is the case if and only if one of the vertex links is closed and not a 2-sphere. Note that the triangulation is not required to be valid.

Returns
true if and only if this triangulation is ideal.

◆ isIrreducible()

bool regina::Triangulation< 3 >::isIrreducible ( ) const

Determines whether the underlying 3-manifold (which must be closed) is irreducible.

In other words, this routine determines whether every embedded sphere in the underlying 3-manifold bounds a ball.

If the underlying 3-manifold is orientable, this routine will use fast crushing and branch-and-bound methods. If the underlying 3-manifold is non-orientable, it will use a (much slower) full enumeration of vertex normal surfaces.

Warning
The algorithms used in this routine rely on normal surface theory and might be slow for larger triangulations.
Precondition
This triangulation is valid, closed, orientable and connected.
Returns
true if and only if the underlying 3-manifold is irreducible.

◆ isIsomorphicTo()

std::optional< Isomorphism< dim > > regina::detail::TriangulationBase< dim >::isIsomorphicTo ( const Triangulation< dim > & other) const
inlineinherited

Determines if this triangulation is combinatorially isomorphic to the given triangulation.

Two triangulations are isomorphic if and only it is possible to relabel their top-dimensional simplices and the (dim+1) vertices of each simplex in a way that makes the two triangulations combinatorially identical, as returned by the equality test t1 == t2.

Equivalently, two triangulations are isomorphic if and only if there is a one-to-one and onto boundary complete combinatorial isomorphism from this triangulation to other, as described in the Isomorphism class notes.

In particular, like the equality test, this routine does not examine or compare simplex/facet locks.

If the triangulations are isomorphic, then this routine returns one such boundary complete isomorphism (i.e., one such relabelling). Otherwise it returns no value . Thus, to test whether an isomorphism exists, you can just call if (isIsomorphicTo(other)).

There may be many such isomorphisms between the two triangulations. If you need to find all such isomorphisms, you may call findAllIsomorphisms() instead.

If you need to ensure that top-dimensional simplices are labelled the same in both triangulations (i.e., that the triangulations are related by the identity isomorphism), you should use the stricter equality test t1 == t2 instead.

Warning
For large dimensions, this routine can become extremely slow: its running time includes a factor of (dim+1)!.
Todo
Optimise: Improve the complexity by choosing a simplex mapping from each component and following gluings to determine the others.
Parameters
otherthe triangulation to compare with this one.
Returns
details of the isomorphism if the two triangulations are combinatorially isomorphic, or no value otherwise.

◆ isOneEfficient()

bool regina::Triangulation< 3 >::isOneEfficient ( ) const

Determines if this triangulation is 1-efficient.

For now, 1-efficiency testing is only available for ideal triangulations in which every vertex link is a torus or Klein bottle. In this setting, an ideal triangulation T is 1-efficient if, amongst all closed embedded normal surfaces in T, there are no surfaces at all of positive Euler characteristic, and the only surfaces with zero Euler characteristic are vertex linking.

The scope of 1-efficiency testing might be expanded to a broader class of triangulations in future versions of Regina; what is currently holding this back is the need to choose from the several different definitions available in the literature.

Precondition
This is a valid ideal triangulation in which the link of every vertex is a torus or Klein bottle.
Exceptions
FailedPreconditionThis triangulation is invalid, empty, and/or has some vertex whose link is not a torus or Klein bottle.
Returns
true if and only if this triangulation is 1-efficient.

◆ isOrdered()

bool regina::Triangulation< 3 >::isOrdered ( ) const

Determines if this triangulation is ordered; that is, if tetrahedron vertices are labelled so that all gluing permutations are order-preserving on the tetrahedron faces.

Equivalently, this tests whether the edges of the triangulation can all be oriented such that they induce a consistent ordering on the vertices of each tetrahedron.

Triangulations are not ordered by default, and indeed some cannot be ordered at all. The routine order() will attempt to relabel tetrahedron vertices to give an ordered triangulation.

Returns
true if and only if all gluing permutations are order preserving on the tetrahedron faces.
Author
Matthias Goerner

◆ isOrientable()

bool regina::detail::TriangulationBase< dim >::isOrientable ( ) const
inlineinherited

Determines if this triangulation is orientable.

Returns
true if and only if this triangulation is orientable.

◆ isOriented()

bool regina::detail::TriangulationBase< dim >::isOriented ( ) const
inherited

Determines if this triangulation is oriented; that is, if the vertices of its top-dimensional simplices are labelled in a way that preserves orientation across adjacent facets.

Specifically, this routine returns true if and only if every gluing permutation has negative sign.

Note that orientable triangulations are not always oriented by default. You can call orient() if you need the top-dimensional simplices to be oriented consistently as described above.

A non-orientable triangulation can never be oriented.

Returns
true if and only if all top-dimensional simplices are oriented consistently.
Author
Matthias Goerner

◆ isoSig()

Encoding::Signature regina::detail::TriangulationBase< dim >::isoSig ( ) const
inherited

Constructs the isomorphism signature of the given type for this triangulation.

Support for different types of signature is new to Regina 7.0 (see below for details); all isomorphism signatures created in Regina 6.0.1 or earlier are of the default type IsoSigClassic.

An isomorphism signature is a compact representation of a triangulation that uniquely determines the triangulation up to combinatorial isomorphism. That is, for any fixed signature type T, two triangulations of dimension dim are combinatorially isomorphic if and only if their isomorphism signatures of type T are the same.

By default, isomorphism signatures support simplex and facet locks: this means that locks are encoded in the isomorphism signature, and the "combinatorial isomorphisms" mentioned above must respect not just the gluings between simplices but also any simplex and/or facet locks. You can change this behaviour by requesting a different encoding (such as IsoSigPrintableLockFree). Under the default encoding, if this triangulation does not have any simplex and/or facet locks then the isomorphism signature will look the same as it did in Regina 7.3.x and earlier, before locks were supported.

The length of an isomorphism signature is proportional to n log n, where n is the number of top-dimenisonal simplices. The time required to construct it is worst-case O((dim!) n² log² n). Whilst this is fine for large triangulations, it becomes very slow for large dimensions; the main reason for introducing different signature types is that some alternative types can be much faster to compute in practice.

Whilst the format of an isomorphism signature bears some similarity to dehydration strings for 3-manifolds, they are more general: isomorphism signatures can be used with any triangulations, including closed, bounded and/or disconnected triangulations, as well as triangulations with many simplices. Note also that 3-manifold dehydration strings are not unique up to isomorphism (they depend on the particular labelling of tetrahedra).

The routine fromIsoSig() can be used to recover a triangulation from an isomorphism signature (only if the default encoding has been used, but it does not matter which signature type was used). The triangulation recovered might not be identical to the original, but it will be combinatorially isomorphic. If you need the precise relabelling, you can call isoSigDetail() instead.

Regina supports several different variants of isomorphism signatures, which are tailored to different computational needs; these are currently determined by the template parameters Type and Encoding:

  • The Type parameter identifies which signature type is to be constructed. Essentially, different signature types use different rules to determine which labelling of a triangulation is "canonical". The default type IsoSigClassic is slow (it never does better than the worst-case time described above); its main advantage is that it is consistent with the original implementation of isomorphism signatures in Regina 4.90.
  • The Encoding parameter controls how Regina encodes a canonical labelling into a final signature. The default encoding IsoSigPrintable returns a std::string consisting entirely of printable characters in the 7-bit ASCII range. Importantly, this default encoding is currently the only encoding from which Regina can reconstruct a triangulation (including any simplex and/or facet locks) from its isomorphism signature.

You may instead pass your own type and/or encoding parameters as template arguments. Currently this facility is for internal use only, and the requirements for type and encoding parameters may change in future versions of Regina. At present:

  • The Type parameter should be a class that is constructible from a componenent reference, and that offers the member functions simplex(), perm() and next(); see the implementation of IsoSigClassic for details.
  • The Encoding parameter should be a class that offers a Signature type alias, and static functions emptySig() and encode(). See the implementation of IsoSigPrintable for details.
  • If you wish to produce an isomorphism signature that ignores simplex and/or facet locks then you can use an encoding whose encode() function ignores the final locks argument, such as IsoSigPrintableLockFree.

For a full and precise description of the classic isomorphism signature format for 3-manifold triangulations, see Simplification paths in the Pachner graphs of closed orientable 3-manifold triangulations, Burton, 2011, arXiv:1110.6080. The format for other dimensions is essentially the same, but with minor dimension-specific adjustments.

Python
Although this is a templated function, all of the variants supplied with Regina are available to Python users. To use the default signature type and encoding, just call isoSig(). To use a non-default signature type, add a suffix _Type where Type is an abbreviated version of the signature type (e.g., isoSig_EdgeDegrees() for the signature type IsoSigEdgeDegrees). To use the encoding IsoSigPrintableLockFree (the only non-default encoding available at present), add another suffix _LockFree (e.g., isoSig_LockFree(), or isoSig_EdgeDegrees_LockFree()).
Warning
Do not mix isomorphism signatures between dimensions! It is possible that the same string could corresponding to both a p-dimensional triangulation and a q-dimensional triangulation for different dimensions p and q.
Returns
the isomorphism signature of this triangulation.

◆ isoSigComponentSize()

static size_t regina::detail::TriangulationBase< dim >::isoSigComponentSize ( const std::string & sig)
staticinherited

Deduces the number of top-dimensional simplices in a connected triangulation from its isomorphism signature.

See isoSig() for more information on isomorphism signatures. It will be assumed that the signature describes a triangulation of dimension dim.

Currently this routine only supports isomorphism signatures that were created with the default encoding (i.e., there was no Encoding template parameter passed to isoSig()).

If the signature describes a connected triangulation, this routine will simply return the size of that triangulation (e.g., the number of tetrahedra in the case dim = 3). You can also pass an isomorphism signature that describes a disconnected triangulation; however, this routine will only return the number of top-dimensional simplices in the first connected component. If you need the total size of a disconnected triangulation, you will need to reconstruct the full triangulation by calling fromIsoSig() instead.

This routine is very fast, since it only examines the first few characters of the isomorphism signature (in which the size of the first component is encoded). However, a side-effect of this is that it is possible to pass an invalid isomorphism signature and still receive a positive result. If you need to test whether a signature is valid or not, you must call fromIsoSig() instead, which will examine the entire signature in full.

Warning
Do not mix isomorphism signatures between dimensions! It is possible that the same string could corresponding to both a p-dimensional triangulation and a q-dimensional triangulation for different dimensions p and q.
Parameters
sigthe isomorphism signature of a dim-dimensional triangulation. Note that isomorphism signature are case-sensitive (unlike, for example, dehydration strings for 3-manifolds).
Returns
the number of top-dimensional simplices in the first connected component, or 0 if this could not be determined because the given string was not a valid isomorphism signature created using the default encoding.

◆ isoSigDetail()

std::pair< typename Encoding::Signature, Isomorphism< dim > > regina::detail::TriangulationBase< dim >::isoSigDetail ( ) const
inherited

Constructs the isomorphism signature for this triangulation, along with the relabelling that will occur when the triangulation is reconstructed from it.

Essentially, an isomorphism signature is a compact representation of a triangulation that uniquely determines the triangulation up to combinatorial isomorphism. See isoSig() for much more detail on isomorphism signatures as well as the support for different signature types and encodings.

As described in the isoSig() notes, you can call fromIsoSig() to recover a triangulation from an isomorphism signature (assuming the default encoding was used). Whilst the triangulation that is recovered will be combinatorially isomorphic to the original, it might not be identical. This routine returns not only the isomorphism signature, but also an isomorphism that describes the precise relationship between this triangulation and the reconstruction from fromIsoSig().

Specifically, if this routine returns the pair (sig, relabelling), this means that the triangulation reconstructed from fromIsoSig(sig) will be identical to relabelling(this).

Python
Although this is a templated function, all of the variants supplied with Regina are available to Python users. To use the default signature type and encoding, just call isoSigDetail(). To use a non-default signature type, add a suffix _Type where Type is an abbreviated version of the signature type (e.g., isoSigDetail_EdgeDegrees() for the signature type IsoSigEdgeDegrees). To use the encoding IsoSigPrintableLockFree (the only non-default encoding available at present), add another suffix _LockFree (e.g., isoSigDetail_LockFree(), or isoSigDetail_EdgeDegrees_LockFree()).
Precondition
This triangulation must be non-empty and connected. The facility to return a relabelling for disconnected triangulations may be added to Regina in a later release.
Exceptions
FailedPreconditionThis triangulation is either empty or disconnected.
Returns
a pair containing (i) the isomorphism signature of this triangulation, and (ii) the isomorphism between this triangulation and the triangulation that would be reconstructed from fromIsoSig().

◆ isReadOnlySnapshot()

bool regina::Snapshottable< Triangulation< dim > >::isReadOnlySnapshot ( ) const
inlineinherited

Determines if this object is a read-only deep copy that was created by a snapshot.

Recall that, if an image I of type T has a snapshot pointing to it, and if that image I is about to be modified or destroyed, then the snapshot will make an internal deep copy of I and refer to that instead.

The purpose of this routine is to identify whether the current object is such a deep copy. This may be important information, since a snapshot's deep copy is read-only: it must not be modified or destroyed by the outside world. (Of course the only way to access this deep copy is via const reference from the SnapshotRef dereference operators, but there are settings in which this constness is "forgotten", such as Regina's Python bindings.)

Returns
true if and only if this object is a deep copy that was taken by a Snapshot object of some original type T image.

◆ isSnapPea() [1/2]

Returns the SnapPea triangulation that holds this data, if there is one.

This routine essentially replaces a dynamic_cast, since the class Triangulation<3> is not polymorphic.

If this object in fact belongs to a SnapPeaTriangulation t (through its inherited Triangulation<3> interface), then this routine will return t. Otherwise it will return null.

Returns
the SnapPea triangulation that holds this data, or null if this data is not part of a SnapPea triangulation.

◆ isSnapPea() [2/2]

const SnapPeaTriangulation * regina::Triangulation< 3 >::isSnapPea ( ) const

Returns the SnapPea triangulation that holds this data, if there is one.

This routine essentially replaces a dynamic_cast, since the class Triangulation<3> is not polymorphic.

If this object in fact belongs to a SnapPeaTriangulation t (through its inherited Triangulation<3> interface), then this routine will return t. Otherwise it will return null.

Returns
the SnapPea triangulation that holds this data, or null if this data is not part of a SnapPea triangulation.

◆ isSolidTorus()

bool regina::Triangulation< 3 >::isSolidTorus ( ) const

Determines whether this is a triangulation of the solid torus; that is, the unknot complement.

This routine can be used on a triangulation with real boundary triangles, or on an ideal triangulation (in which case all ideal vertices will be assumed to be truncated).

Warning
The algorithms used in this routine rely on normal surface theory and so might be very slow for larger triangulations (although faster tests are used where possible). The routine knowsSolidTorus() can be called to see if this property is already known or if it happens to be very fast to calculate for this triangulation.
Returns
true if and only if this is either a real (compact) or ideal (non-compact) triangulation of the solid torus.

◆ isSphere()

bool regina::Triangulation< 3 >::isSphere ( ) const

Determines whether this is a triangulation of a 3-sphere.

This routine relies upon a combination of Rubinstein's 3-sphere recognition algorithm and Jaco and Rubinstein's 0-efficiency prime decomposition algorithm.

Warning
The algorithms used in this routine rely on normal surface theory and so can be very slow for larger triangulations (although faster tests are used where possible). The routine knowsSphere() can be called to see if this property is already known or if it happens to be very fast to calculate for this triangulation.
Returns
true if and only if this is a 3-sphere triangulation.

◆ isStandard()

bool regina::Triangulation< 3 >::isStandard ( ) const
inline

Determines if this triangulation is standard.

This is the case if and only if every vertex is standard. See Vertex<3>::isStandard() for further details.

Returns
true if and only if this triangulation is standard.

◆ isTxI()

bool regina::Triangulation< 3 >::isTxI ( ) const

Determines whether or not the underlying 3-manifold is the product of a torus with an interval.

This routine can be used on a triangulation with real boundary triangles, or ideal boundary components, or a mix of both. If there are any ideal vertices, they will be treated as though they were truncated.

The underlying algorithm is due to Robert C. Haraway, III; see https://journals.carleton.ca/jocg/index.php/jocg/article/view/433 for details.

Warning
This algorithm ultimately relies on isSolidTorus(), which might run slowly for large triangulations.
Returns
true if and only if this is a triangulation (either real, ideal or a combination) of the product of the torus with an interval.

◆ isValid()

bool regina::detail::TriangulationBase< dim >::isValid ( ) const
inlineinherited

Determines if this triangulation is valid.

There are several conditions that might make a dim-dimensional triangulation invalid:

  1. if some face is identified with itself under a non-identity permutation (e.g., an edge is identified with itself in reverse, or a triangle is identified with itself under a rotation);
  2. if some subdim-face does not have an appropriate link. Here the meaning of "appropriate" depends upon the type of face:
    • for a face that belongs to some boundary facet(s) of this triangulation, its link must be a topological ball;
    • for a vertex that does not belong to any boundary facets, its link must be a closed (dim - 1)-manifold;
    • for a (subdim ≥ 1)-face that does not belong to any boundary facets, its link must be a topological sphere.

Condition (1) is tested for all dimensions dim. Condition (2) is more difficult, since it relies on undecidable problems. As a result, (2) is only tested when dim is one of Regina's standard dimensions.

If a triangulation is invalid then you can call Face<dim, subdim>::isValid() to discover exactly which face(s) are responsible, and you can call Face<dim, subdim>::hasBadIdentification() and/or Face<dim, subdim>::hasBadLink() to discover exactly which conditions fail.

Note that all invalid vertices are considered to be on the boundary; see isBoundary() for details.

Returns
true if and only if this triangulation is valid.

◆ isZeroEfficient()

bool regina::Triangulation< 3 >::isZeroEfficient ( ) const

Determines if this triangulation is 0-efficient.

A triangulation is 0-efficient if its only normal spheres and discs are vertex linking, and if it has no 2-sphere boundary components.

Returns
true if and only if this triangulation is 0-efficient.

◆ knowsBall()

bool regina::Triangulation< 3 >::knowsBall ( ) const

Is it already known (or trivial to determine) whether or not this is a triangulation of a 3-dimensional ball? See isBall() for further details.

If this property is indeed already known, future calls to isBall() will be very fast (simply returning the precalculated value).

If this property is not already known, this routine will nevertheless run some very fast preliminary tests to see if the answer is obviously no. If so, it will store false as the precalculated value for isBall() and this routine will return true.

Otherwise a call to isBall() may potentially require more significant work, and so this routine will return false.

Warning
This routine does not actually tell you whether this triangulation forms a ball; it merely tells you whether the answer has already been computed (or is very easily computed).
Returns
true if and only if this property is already known or trivial to calculate.

◆ knowsCompressingDisc()

bool regina::Triangulation< 3 >::knowsCompressingDisc ( ) const

Is it already known (or trivial to determine) whether or not the underlying 3-manifold contains a compressing disc? See hasCompressingDisc() for further details.

If this property is indeed already known, future calls to hasCompressingDisc() will be very fast (simply returning the precalculated value).

If this property is not already known, this routine will nevertheless run some very fast preliminary tests to see if the answer is obviously no. If so, it will store false as the precalculated value for hasCompressingDisc() and this routine will return true.

Otherwise a call to hasCompressingDisc() may potentially require more significant work, and so this routine will return false.

Warning
This routine does not actually tell you whether the underlying 3-manifold has a compressing disc; it merely tells you whether the answer has already been computed (or is very easily computed).
Precondition
This triangulation is valid and is not ideal.
The underlying 3-manifold is irreducible.
Returns
true if and only if this property is already known or trivial to calculate.

◆ knowsHaken()

bool regina::Triangulation< 3 >::knowsHaken ( ) const

Is it already known (or trivial to determine) whether or not the underlying 3-manifold is Haken? See isHaken() for further details.

If this property is indeed already known, future calls to isHaken() will be very fast (simply returning the precalculated value).

Warning
This routine does not actually tell you whether the underlying 3-manifold is Haken; it merely tells you whether the answer has already been computed (or is very easily computed).
Precondition
This triangulation is valid, closed, orientable and connected.
Returns
true if and only if this property is already known or trivial to calculate.

◆ knowsHandlebody()

bool regina::Triangulation< 3 >::knowsHandlebody ( ) const

Is it already known (or trivial to determine) whether or not this is a triangulation of an orientable handlebody? See recogniseHandlebody() for further details.

If this property is indeed already known, future calls to recogniseHandlebody() will be very fast (simply returning the precalculated value).

If this property is not already known, this routine will nevertheless run some very fast preliminary tests to see if the answer is obviously no. If so, it will store false as the precalculated value for recogniseHandlebody() and this routine will return true.

Otherwise a call to recogniseHandlebody() may potentially require more significant work, and so this routine will return false.

Warning
This routine does not actually tell you whether this triangulation forms an orientable handlebody; it merely tells you whether the answer has already been computed (or is very easily computed).
Returns
true if and only if this property is already known or trivial to calculate.
Author
Alex He

◆ knowsIrreducible()

bool regina::Triangulation< 3 >::knowsIrreducible ( ) const

Is it already known (or trivial to determine) whether or not the underlying 3-manifold is irreducible? See isIrreducible() for further details.

If this property is indeed already known, future calls to isIrreducible() will be very fast (simply returning the precalculated value).

Warning
This routine does not actually tell you whether the underlying 3-manifold is irreducible; it merely tells you whether the answer has already been computed (or is very easily computed).
Precondition
This triangulation is valid, closed, orientable and connected.
Returns
true if and only if this property is already known or trivial to calculate.

◆ knowsOneEfficient()

bool regina::Triangulation< 3 >::knowsOneEfficient ( ) const
inline

Is it already known whether or not this triangulation is 1-efficient? See isOneEfficient() for further details.

If this property is already known, future calls to isOneEfficient() will be very fast (simply returning the precalculated value).

Precondition
This is a valid ideal triangulation in which the link of every vertex is a torus or Klein bottle.
Warning
This routine does not actually tell you whether this triangulation is 1-efficient; it merely tells you whether the answer has already been computed.
Exceptions
FailedPreconditionThis triangulation is invalid, empty, and/or has some vertex whose link is not a torus or Klein bottle.
Returns
true if and only if this property is already known.

◆ knowsSolidTorus()

bool regina::Triangulation< 3 >::knowsSolidTorus ( ) const

Is it already known (or trivial to determine) whether or not this is a triangulation of a solid torus (that is, the unknot complement)? See isSolidTorus() for further details.

If this property is indeed already known, future calls to isSolidTorus() will be very fast (simply returning the precalculated value).

If this property is not already known, this routine will nevertheless run some very fast preliminary tests to see if the answer is obviously no. If so, it will store false as the precalculated value for isSolidTorus() and this routine will return true.

Otherwise a call to isSolidTorus() may potentially require more significant work, and so this routine will return false.

Warning
This routine does not actually tell you whether this triangulation forms a solid torus; it merely tells you whether the answer has already been computed (or is very easily computed).
Returns
true if and only if this property is already known or trivial to calculate.

◆ knowsSphere()

bool regina::Triangulation< 3 >::knowsSphere ( ) const

Is it already known (or trivial to determine) whether or not this is a triangulation of a 3-sphere? See isSphere() for further details.

If this property is indeed already known, future calls to isSphere() will be very fast (simply returning the precalculated value).

If this property is not already known, this routine will nevertheless run some very fast preliminary tests to see if the answer is obviously no. If so, it will store false as the precalculated value for isSphere() and this routine will return true.

Otherwise a call to isSphere() may potentially require more significant work, and so this routine will return false.

Warning
This routine does not actually tell you whether this triangulation forms a 3-sphere; it merely tells you whether the answer has already been computed (or is very easily computed).
Returns
true if and only if this property is already known or trivial to calculate.

◆ knowsStrictAngleStructure()

bool regina::Triangulation< 3 >::knowsStrictAngleStructure ( ) const

Is it already known (or trivial to determine) whether or not this triangulation supports a strict angle structure? See hasStrictAngleStructure() for further details.

If this property is indeed already known, future calls to strictAngleStructure() and hasStrictAngleStructure() will be very fast (simply returning the precalculated solution).

Warning
This routine does not actually tell you whether the triangulation supports a strict angle structure; it merely tells you whether the answer has already been computed (or is very easily computed).
Returns
true if and only if this property is already known or trivial to calculate.

◆ knowsTxI()

bool regina::Triangulation< 3 >::knowsTxI ( ) const

Is it already known (or trivial to determine) whether or not this is a triangulation of a the product of a torus with an interval? See isTxI() for further details.

If this property is indeed already known, future calls to isTxI() will be very fast (simply returning the precalculated value).

If this property is not already known, this routine will nevertheless run some very fast preliminary tests to see if the answer is obviously no. If so, it will store false as the precalculated value for isTxI() and this routine will return true.

Otherwise a call to isTxI() may potentially require more significant work, and so this routine will return false.

Warning
This routine does not actually tell you whether this triangulation forms the product of the torus with an interval; it merely tells you whether the answer has already been computed (or is very easily computed).
Returns
true if and only if this property is already known or trivial to calculate.

◆ knowsZeroEfficient()

bool regina::Triangulation< 3 >::knowsZeroEfficient ( ) const
inline

Is it already known whether or not this triangulation is 0-efficient? See isZeroEfficient() for further details.

If this property is already known, future calls to isZeroEfficient() will be very fast (simply returning the precalculated value).

Warning
This routine does not actually tell you whether this triangulation is 0-efficient; it merely tells you whether the answer has already been computed.
Returns
true if and only if this property is already known.

◆ layerOn()

Tetrahedron< 3 > * regina::Triangulation< 3 >::layerOn ( Edge< 3 > * edge)

Performs a layering upon the given boundary edge of the triangulation.

See the Layering class notes for further details on what a layering entails.

The new tetrahedron will be returned, and the new boundary edge that it creates will be edge 5 (i.e., the edge joining vertices 2 and 3) of this tetrahedron.

Precondition
The given edge is a boundary edge of this triangulation, and the two boundary triangles on either side of it are distinct.
Exceptions
InvalidArgumentThe preconditions above do not hold; that is, either the given edge is non-boundary, or the same boundary triangles lie on both sides of it.
LockViolationAt least one of the two boundary triangles on either side of the given edge is currently locked. This exception will be thrown before any changes are made. See Simplex<3>::lockFacet() for further details on how such locks work and what their implications are.
Parameters
edgethe boundary edge upon which to layer.
Returns
the new tetrahedron provided by the layering.

◆ linkingSurface()

template<int subdim>
std::pair< NormalSurface, bool > regina::Triangulation< 3 >::linkingSurface ( const Face< 3, subdim > & face) const

Returns the link of the given face as a normal surface.

Constructing the link of a face begins with building the frontier of a regular neighbourhood of the face. If this is already a normal surface, then then link is called thin. Otherwise the usual normalisation steps are performed until the surface becomes normal; note that these normalisation steps could change the topology of the surface, and in some pathological cases could even reduce it to the empty surface.

Template Parameters
subdimthe dimension of the face to link; this must be between 0 and 2 inclusive.
Precondition
The given face is a face of this triangulation.
Returns
a pair (s, thin), where s is the face linking normal surface, and thin is true if and only if this link is thin (i.e., no additional normalisation steps were required).

◆ lockBoundary()

void regina::detail::TriangulationBase< dim >::lockBoundary ( )
inherited

Locks all boundary facets of this triangulation.

In short, this means that the boundary facets must not be changed. See Simplex<dim>::lockFacet() for full details on how locks work and what their implications are.

If there are any other locks on top-dimensional simplices and/or their facets, these other locks will be left intact.

Note that this only locks the facets of real boundary components. Ideal boundary components are not affected (since they have no facets to lock).

◆ longitude()

Edge< 3 > * regina::Triangulation< 3 >::longitude ( )

Modifies a triangulated knot complement so that the algebraic longitude follows a single boundary edge, and returns this edge.

Assuming that this triangulation represents the complement of a knot in the 3-sphere, this routine:

  • identifies the algebraic longitude of the knot complement; that is, identifies the non-trivial simple closed curve on the boundary whose homology in the 3-manifold is trivial;
  • layers additional tetrahedra on the boundary if necessary so that this curve is represented by a single boundary edge;
  • returns that (possibly new) boundary edge.

Whilst this routine returns less information than meridianLongitude(), it (1) runs much faster since it is based on fast algebraic calculations, and (2) guarantees to terminate. In contrast, meridianLongitude() must repeatedly try to test for 3-spheres, and (as a result of only using fast 3-sphere recognition heuristics) does not guarantee to terminate.

At present this routine is fairly restrictive in what triangulations it can work with: it requires the triangulation to be one-vertex and have real (not ideal) boundary. These restrictions may be eased in future versions of Regina.

If the algebraic longitude is already represented by a single boundary edge, then it is guaranteed that this routine will not modify the triangulation, and will simply return this boundary edge.

Precondition
The underlying 3-manifold is known to be the complement of a knot in the 3-sphere.
This triangulation has precisely one vertex, and its (unique) boundary component is formed from two triangles.
Warning
This routine may modify the triangluation, as explained above, which will have the side-effect of invalidating any existing Vertex, Edge or Triangle references.
If you have an ideal triangulation of a knot complement, you must first run truncateIdeal() and then simplify the resulting triangulation to have two boundary triangles.
Exceptions
FailedPreconditionThis triangulation is not a valid one-vertex orientable triangulation with homology Z, and with a two-triangle torus as its one and only boundary component. Note that this does not capture all of the preconditions for this routine, but it does capture those that are easy to test.
UnsolvedCaseAn integer overflow occurred during the computation.
LockViolationAt least one of the two boundary triangles is currently locked. This exception will be thrown before any changes are made. See Simplex<3>::lockFacet() for further details on how such locks work and what their implications are.
Returns
the boundary edge representing the algebraic longitude of the knot (after this triangulation has been modified if necessary).

◆ longitudeCuts()

std::array< long, 3 > regina::Triangulation< 3 >::longitudeCuts ( ) const

Identifies the algebraic longitude as a curve on the boundary of a triangulated knot complement.

Specifically, assuming that this triangulation represents the complement of a knot in the 3-sphere, this routine identifies the non-trivial simple closed curve on the boundary whose homology in the 3-manifold is trivial.

The curve will be returned as a triple of integers, indicating how many times the longitude intersects each of the three boundary edges. It is always true that the largest of these three integers will be the sum of the other two.

At present this routine is fairly restrictive in what triangulations it can work with: it requires the triangulation to be one-vertex and have real (not ideal) boundary. These restrictions may be eased in future versions of Regina.

Precondition
The underlying 3-manifold is known to be the complement of a knot in the 3-sphere.
This triangulation has precisely one vertex, and its (unique) boundary component is formed from two triangles.
Warning
If you have an ideal triangulation of a knot complement, you must first run truncateIdeal() and then simplify the resulting triangulation to have two boundary triangles.
Exceptions
FailedPreconditionThis triangulation is not a valid one-vertex orientable triangulation with homology Z, and with a two-triangle torus as its one and only boundary component. Note that this does not capture all of the preconditions for this routine, but it does capture those that are easy to test.
UnsolvedCaseAn integer overflow occurred during the computation.
Returns
a triple of non-negative integers indicating how many times the longitude intersects each of the three boundary edges. Specifically, if the returned tuple is t and the unique boundary component is bc, then for each k = 0,1,2, the element t[k] indicates the (absolute) number of times that the longitude intersects the edge bc->edge(k).

◆ makeCanonical()

bool regina::detail::TriangulationBase< dim >::makeCanonical ( )
inherited

Relabel the top-dimensional simplices and their vertices so that this triangulation is in canonical form.

This is essentially the lexicographically smallest labelling when the facet gluings are written out in order.

Two triangulations are isomorphic if and only if their canonical forms are identical.

The lexicographic ordering assumes that the facet gluings are written in order of simplex index and then facet number. Each gluing is written as the destination simplex index followed by the gluing permutation (which in turn is written as the images of 0,1,...,dim in order).

If this triangulation has any locks on its top-dimensional simplices and/or their facets, this routine will carry the locks through the relabelling correctly. Locks do not play any role in determining which labelling is canonical (i.e., the canonical labelling will be the same regardles of whether or not there are locks present).

Precondition
This routine currently works only when the triangulation is connected. It may be extended to work with disconnected triangulations in later versions of Regina.
Returns
true if the triangulation was changed, or false if the triangulation was in canonical form to begin with.

◆ makeDoubleCover()

void regina::detail::TriangulationBase< dim >::makeDoubleCover ( )
inherited

Deprecated routine that converts this triangulation into its orientable double cover.

This triangulation wll be modified directly.

Deprecated
This routine has been replaced by doubleCover(), which returns the result as a new triangulation and leaves the original triangulation untouched.

See doubleCover() for further details.

◆ makeIdeal()

bool regina::detail::TriangulationBase< dim >::makeIdeal ( )
inherited

Converts each real boundary component into a cusp (i.e., an ideal vertex).

Only boundary components formed from real (dim-1)-faces will be affected; ideal boundary components are already cusps and so will not be changed.

One side-effect of this operation is that all spherical boundary components will be filled in with balls.

This operation is performed by attaching a new dim-simplex to each boundary (dim-1)-face, and then gluing these new simplices together in a way that mirrors the adjacencies of the underlying boundary facets. Each boundary component will thereby be pushed up through the new simplices and converted into a cusp formed using vertices of these new simplices.

In Regina's standard dimensions, where triangulations also support a truncateIdeal() operation, this routine is a loose converse of that operation.

In dimension 2, every boundary component is spherical and so this routine simply fills all the punctures in the underlying surface. (In dimension 2, triangulations cannot have cusps).

A note: this operation does not preserve orientedness. That is, even if this triangulation was oriented before calling this function, it might not be oriented after. This behaviour may change in a future version of Regina.

Warning
If a real boundary component contains vertices whose links are not discs, this operation may have unexpected results.
Exceptions
LockViolationThis triangulation contains at least one locked boundary facet. This exception will be thrown before any changes are made. See Simplex<dim>::lockFacet() for further details on how such locks work and what their implications are.
Returns
true if changes were made, or false if the original triangulation contained no real boundary components.

◆ markedHomology() [1/2]

MarkedAbelianGroup regina::detail::TriangulationBase< dim >::markedHomology ( ) const
inlineinherited

Returns the kth homology group of this triangulation, without truncating ideal vertices, but with explicit coordinates that track the individual k-faces of this triangulation.

For C++ programmers who know subdim at compile time, you should use this template function markedHomology<subdim>(), which is slightly faster than passing subdim as an ordinary runtime argument to markedHomology(subdim).

See the non-templated markedHomology(int) for full details on what this function computes, some important caveats to be aware of, and how the group that it returns should be interpreted.

Precondition
This triangulation is valid and non-empty.
Exceptions
FailedPreconditionThis triangulation is empty or invalid.
Python
Not present. Instead use the variant markedHomology(k).
Template Parameters
kthe dimension of the homology group to compute; this must be between 1 and (dim-1) inclusive.
Returns
the kth homology group of the union of all simplices in this triangulation, as described above.

◆ markedHomology() [2/2]

MarkedAbelianGroup regina::detail::TriangulationBase< dim >::markedHomology ( int k) const
inlineinherited

Returns the kth homology group of this triangulation, without truncating ideal vertices, but with explicit coordinates that track the individual k-faces of this triangulation, where the parameter k does not need to be known until runtime.

For C++ programmers who know k at compile time, you are better off using the template function markedHomology<k>() instead, which is slightly faster.

This is a specialised homology routine; you should only use it if you need to understand how individual k-faces (or chains of k-faces) appear within the homology group.

  • The major disadvantage of this routine is that it does not truncate ideal vertices. Instead it computes the homology of the union of all top-dimensional simplices, working directly with the boundary maps between (k+1)-faces, k-faces and (k-1)-faces of the triangulation. If your triangulation is ideal, then this routine will almost certainly not give the correct homology group for the underlying manifold. If, however, all of your vertex links are spheres or balls (i.e., the triangulation is closed or all of its boundary components are built from unglued (dim-1)-faces), then the homology of the manifold will be computed correctly.
  • The major advantage is that, instead of returning a simpler AbelianGroup, this routine returns a MarkedAbelianGroup. This allows you to track chains of individual k-faces of the triangulation as they appear within the homology group. Specifically, the chain complex cordinates with this MarkedAbelianGroup represent precisely the k-faces of the triangulation in the same order as they appear in the list faces<k>(), using the inherent orientation provided by Face<dim, k>.
Precondition
This triangulation is valid and non-empty.
Exceptions
FailedPreconditionThis triangulation is empty or invalid.
InvalidArgumentThe homology dimension k is outside the supported range (i.e., less than 1 or greater than or equal to dim).
Python
Like the C++ template function markedHomology<k>(), you can omit the homology dimension k; this will default to 1.
Parameters
kthe dimension of the homology group to compute; this must be between 1 and (dim-1) inclusive.
Returns
the kth homology group of the union of all simplices in this triangulation, as described above.

◆ maximalForestInBoundary()

std::set< Edge< 3 > * > regina::Triangulation< 3 >::maximalForestInBoundary ( ) const

Produces a maximal forest in the 1-skeleton of the triangulation boundary.

Note that the edge pointers returned will become invalid once the triangulation has changed.

Returns
a set containing the edges of the maximal forest.

◆ maximalForestInSkeleton()

std::set< Edge< 3 > * > regina::Triangulation< 3 >::maximalForestInSkeleton ( bool canJoinBoundaries = true) const

Produces a maximal forest in the triangulation's 1-skeleton.

It can be specified whether or not different boundary components may be joined by the maximal forest.

An edge leading to an ideal vertex is still a candidate for inclusion in the maximal forest. For the purposes of this algorithm, any ideal vertex will be treated as any other vertex (and will still be considered part of its own boundary component).

Note that the edge pointers returned will become invalid once the triangulation has changed.

Parameters
canJoinBoundariestrue if and only if different boundary components are allowed to be joined by the maximal forest.
Returns
a set containing the edges of the maximal forest.

◆ meridian()

Edge< 3 > * regina::Triangulation< 3 >::meridian ( )

Modifies a triangulated knot complement so that the meridian follows a single boundary edge, and returns this edge.

Assuming that this triangulation represents the complement of a knot in the 3-sphere, this routine:

  • identifies the meridian of the knot complement;
  • layers additional tetrahedra on the boundary if necessary so that this curve is represented by a single boundary edge;
  • returns that (possibly new) boundary edge.

This routine uses fast heuristics to locate the meridian; as a result, it does not guarantee to terminate (but if you find a case where it does not, please let the Regina developers know!). If it does return then it guarantees that the result is correct.

This routine uses a similar algorithm to meridianLongitude(), with the same problem that it could be slow and might not terminate. However, meridian() has the advantage that it might produce a smaller triangulation, since there is no need to arrange for the longitude to be a boundary edge also.

At present this routine is fairly restrictive in what triangulations it can work with: it requires the triangulation to be one-vertex and have real (not ideal) boundary. These restrictions may be eased in future versions of Regina.

If the meridian is already represented by a single boundary edge, then it is guaranteed that, if this routine does terminate, it will not modify the triangulation, and will simply return this boundary edge.

Precondition
The underlying 3-manifold is known to be the complement of a knot in the 3-sphere.
This triangulation has precisely one vertex, and its (unique) boundary component is formed from two triangles.
Warning
This routine may modify the triangluation, as explained above, which will have the side-effect of invalidating any existing Vertex, Edge or Triangle references.
If you have an ideal triangulation of a knot complement, you must first run truncateIdeal() and then simplify the resulting triangulation to have two boundary triangles.
Exceptions
FailedPreconditionThis triangulation is not a valid one-vertex orientable triangulation with homology Z, and with a two-triangle torus as its one and only boundary component. Note that this does not capture all of the preconditions for this routine, but it does capture those that are easy to test.
UnsolvedCaseAn integer overflow occurred during the computation.
LockViolationAt least one of the two boundary triangles is currently locked. This exception will be thrown before any changes are made. See Simplex<3>::lockFacet() for further details on how such locks work and what their implications are.
Returns
the boundary edge representing the meridian (after this triangulation has been modified if necessary).

◆ meridianLongitude()

std::pair< Edge< 3 > *, Edge< 3 > * > regina::Triangulation< 3 >::meridianLongitude ( )

Modifies a triangulated knot complement so that the meridian and algebraic longitude each follow a single boundary edge, and returns these two edges.

Assuming that this triangulation represents the complement of a knot in the 3-sphere, this routine:

  • identifies the meridian of the knot complement, and also the algebraic longitude (i.e., the non-trivial simple closed curve on the boundary whose homology in the 3-manifold is trivial);
  • layers additional tetrahedra on the boundary if necessary so that each of these curves is represented by a single boundary edge;
  • returns these two (possibly new) boundary edges.

This routine uses fast heuristics to locate the meridian; as a result, it does not guarantee to terminate (but if you find a case where it does not, please let the Regina developers know!). If it does return then it guarantees that the result is correct.

Whilst this routine returns more information than longitude(), note that longitude() (1) runs much faster since it is based on fast algebraic calculations, and (2) guarantees to terminate.

At present this routine is fairly restrictive in what triangulations it can work with: it requires the triangulation to be one-vertex and have real (not ideal) boundary. These restrictions may be eased in future versions of Regina.

If the meridian and algebraic longitude are already both represented by single boundary edges, then it is guaranteed that, if this routine does terminate, it will not modify the triangulation, and will simply return these two boundary edges.

Precondition
The underlying 3-manifold is known to be the complement of a knot in the 3-sphere.
This triangulation has precisely one vertex, and its (unique) boundary component is formed from two triangles.
Warning
This routine may modify the triangluation, as explained above, which will have the side-effect of invalidating any existing Vertex, Edge or Triangle references.
If you have an ideal triangulation of a knot complement, you must first run truncateIdeal() and then simplify the resulting triangulation to have two boundary triangles.
Exceptions
FailedPreconditionThis triangulation is not a valid one-vertex orientable triangulation with homology Z, and with a two-triangle torus as its one and only boundary component. Note that this does not capture all of the preconditions for this routine, but it does capture those that are easy to test.
UnsolvedCaseAn integer overflow occurred during the computation.
LockViolationAt least one of the two boundary triangles is currently locked. This exception will be thrown before any changes are made. See Simplex<3>::lockFacet() for further details on how such locks work and what their implications are.
Returns
a pair (m, l), where m is the boundary edge representing the meridian and l is the boundary edge representing the algebraic longitude of the knot complement (after this triangulation has been modified if necessary).

◆ minimiseBoundary()

bool regina::Triangulation< 3 >::minimiseBoundary ( )

Ensures that the boundary contains the smallest possible number of triangles, potentially adding tetrahedra to do this.

This routine is for use with algorithms that require minimal boundaries (e.g., torus boundaries must contain exactly two triangles). As noted above, it may in fact increase the total number of tetrahedra in the triangulation (though the implementation does make efforts not to do this).

Once this routine is finished, every boundary component will have exactly one vertex, except for sphere and projective plane boundaries which will have exactly two triangles (but three and two vertices respectively).

The changes that this routine performs can always be expressed using only close book moves and/or layerings. In particular, this routine never creates new vertices, and it never creates a non-vertex-linking normal disc or sphere if there was not one before.

Although this routine only modifies real boundary components, it is fine if the triangulation also contains ideal boundary components (and these simply will be left alone). If the triangulation contains internal vertices, these will likewise be left untouched. If you wish to remove internal vertices also, then you should call minimiseVertices() instead.

If this triangulation is currently oriented, then this operation will preserve the orientation.

If this triangle has any locked tetrahedra or locked internal triangles, such locks will not prevent this operation from occuring (since none of the moves would violate such locks). However, this operation does not try to avoid violating locks on boundary triangles (and indeed, in some scenarios this would be impossible). Therefore we require as a precondition that no boundary triangles are locked.

Precondition
This triangulation is valid.
This triangulation does not have any locked boundary triangles.
Exceptions
FailedPreconditionThis triangulation is not valid.
LockViolationThis operation attempted a move that would violate a lock on a boundary triangle. Note that some moves might have been performed already before this exception is thrown, though the topology of the manifold should remain safely unchanged. See Simplex<3>::lockFacet() for further details on how facet locks work and what their implications are.
Returns
true if the triangulation was changed, or false if every boundary component was already minimal to begin with.

◆ minimiseVertices()

bool regina::Triangulation< 3 >::minimiseVertices ( )

Ensures that this triangulation contains the smallest possible number of vertices for the 3-manifold that it represents, potentially adding tetrahedra to do this.

This routine is for use with algorithms that require a minimal number of vertices (e.g., one-vertex triangulations of closed manifolds, or k-vertex triangulations of the complements of k-component links). As noted above, this routine may in fact increase the total number of tetrahedra in the triangulation (though the implementation does make efforts not to do this).

Once this routine is finished:

  • every real boundary component will have exactly one vertex, except for sphere and projective plane boundaries which will have three and two vertices respectively (i.e., the minimum possible);
  • for each component of the triangulation that contains one or more boundary components (either real and/or ideal), there will be no internal vertices at all;
  • for each component of the triangulation that has no boundary components (i.e., that represents a closed 3-manifold), there will be precisely one vertex.

The changes that this routine performs can always be expressed using only close book moves, layerings, collapse edge moves, and/or pinch edge moves. In particular, this routine never creates new vertices.

If this triangulation is currently oriented, then this operation will preserve the orientation.

If this triangle has any locked tetrahedra or locked internal triangles, such locks will not prevent this operation from occuring (in particular, this routine will use pinch edge moves instead of collapse edge moves where necessary to avoid violating such locks). However, this operation does not try to avoid violating locks on boundary triangles (and indeed, in some scenarios this would be impossible). Therefore we require as a precondition that no boundary triangles are locked.

Precondition
This triangulation is valid.
This triangulation does not have any locked boundary triangles.
Exceptions
FailedPreconditionThis triangulation is not valid.
LockViolationThis operation attempted a move that would violate a lock on a boundary triangle. Note that some moves might have been performed already before this exception is thrown, though the topology of the manifold should remain safely unchanged. See Simplex<3>::lockFacet() for further details on how facet locks work and what their implications are.
Returns
true if the triangulation was changed, or false if the number of vertices was already minimal to begin with.

◆ minimizeBoundary()

bool regina::Triangulation< 3 >::minimizeBoundary ( )
inline

A deprecated synonym for minimiseBoundary().

This ensures that the boundary contains the smallest possible number of triangles, potentially adding tetrahedra to do this.

See minimiseBoundary() for further details.

Deprecated
Regina uses British English throughout its API. This synonym was a special case where Regina used to offer both British and American alternatives, but this will be removed in a future release. See the page on spelling throughout Regina for further details.
Precondition
This triangulation is valid.
This triangulation does not have any locked boundary triangles.
Exceptions
LockViolationThis operation attempted a move that would violate a lock on a boundary triangle. Note that some moves might have been performed already before this exception is thrown, though the topology of the manifold should remain safely unchanged. See Simplex<3>::lockFacet() for further details on how facet locks work and what their implications are.
Returns
true if the triangulation was changed, or false if every boundary component was already minimal to begin with.

◆ minimizeVertices()

bool regina::Triangulation< 3 >::minimizeVertices ( )
inline

A deprecated synonym for minimiseVertices().

This ensures that the triangulation contains the smallest possible number of vertices, potentially adding tetrahedra to do this.

See minimiseVertices() for further details.

Deprecated
Regina uses British English throughout its API. This synonym was a special case where Regina used to offer both British and American alternatives, but this will be removed in a future release. See the page on spelling throughout Regina for further details.
Precondition
This triangulation is valid.
This triangulation does not have any locked boundary triangles.
Exceptions
LockViolationThis operation attempted a move that would violate a lock on a boundary triangle. Note that some moves might have been performed already before this exception is thrown, though the topology of the manifold should remain safely unchanged. See Simplex<3>::lockFacet() for further details on how facet locks work and what their implications are.
Returns
true if the triangulation was changed, or false if the number of vertices was already minimal to begin with.

◆ move02() [1/3]

bool regina::Triangulation< 3 >::move02 ( Edge< 3 > * e,
size_t t0,
size_t t1 )
inline

If possible, performs a 0-2 move about the two specified triangles.

This involves fattening these two triangles (which should share a common edge, and which need not be distinct) into a new pair of tetrahedra surrounding a new degree two edge. This is, in essence, an inverse to the 2-0 edge move.

The different variants of move02() allow the two triangles and their common edge to be specified in different ways. For this variant, the common edge is given as the argument e, and the two triangles are the triangles incident to e that are numbered t0 and t1 (see below for how this numbering scheme works).

This triangulation will be changed directly.

This move will only be performed if it will not change the topology of the manifold (as discussed below), and it will not violate any facet locks. See Simplex<3>::lockFacet() for further details on facet locks. Note that simplex locks are never a concern for this type of move.

To be able to perform this move, we require that:

  • the given edge e is valid;
  • the numbers t0 and t1 are both less than or equal to e->degree(), and strictly less than e->degree() if e is non-boundary (as required by our numbering scheme for triangles).

Our numbering scheme for triangles incident to e works as follows:

  • For each i in the range 0 ≤ i < e->degree(), we assign the number i to the triangle emb.tetrahedron()->triangle(emb.vertices()[3]), where emb denotes e->embedding(i).
  • If e is a boundary edge, then we additionally assign the number e->degree() to the boundary triangle emb.tetrahedron()->triangle(emb.vertices()[2]), where this time emb denotes e->back().

A note regarding facet locks: since this move pries open a pair of adjacent triangles and not just a single triangle, a lock on either of the two triangles involved in this move will prevent the move from taking place.

If this triangulation is currently oriented, then this 0-2 move will label the new tetrahedra in a way that preserves the orientation.

The implementation of this routine simply translates its arguments to call move02(EdgeEmbedding<3>, int, EdgeEmbedding<3>, int).

Note that after performing this move, all skeletal objects (faces, components, etc.) will be reconstructed, which means any pointers to old skeletal objects (such as the argument e) can no longer be used.

Precondition
The given edge is an edge of this triangulation.
Parameters
ethe common edge of the two triangles about which to perform the move.
t0the number assigned to one of two triangles about which to perform the move, as described above.
t1the number assigned to the other triangle about which to perform the move, as described above.
Returns
true if and only if the requested move was able to be performed.
Author
Alex He

◆ move02() [2/3]

bool regina::Triangulation< 3 >::move02 ( EdgeEmbedding< 3 > e0,
int t0,
EdgeEmbedding< 3 > e1,
int t1 )
inline

If possible, performs a 0-2 move about the two specified triangles.

This involves fattening these two triangles (which should share a common edge, and which need not be distinct) into a new pair of tetrahedra surrounding a new degree two edge. This is, in essence, an inverse to the 2-0 edge move.

The different variants of move02() allow the two triangles and their common edge to be specified in different ways. For this variant, the common edge is referenced by both the embedding objects e0 and e1, and the the two triangles are e0.tetrahedron()->triangle(e0.vertices()[t0]) and e1.tetrahedron()->triangle(e1.vertices()[t1]).

This triangulation will be changed directly.

This move will only be performed if it will not change the topology of the manifold (as discussed below), and it will not violate any facet locks. See Simplex<3>::lockFacet() for further details on facet locks. Note that simplex locks are never a concern for this type of move.

To be able to perform this move, we require that:

  • e0 and e1 are both embeddings of the same edge e;
  • this common edge e is valid;
  • t0 and t1 are both either 2 or 3 (which means that the two triangles listed above do indeed contain e).

A note regarding facet locks: since this move pries open a pair of adjacent triangles and not just a single triangle, a lock on either of the two triangles involved in this move will prevent the move from taking place.

If this triangulation is currently oriented, then this 0-2 move will label the new tetrahedra in a way that preserves the orientation.

Note that after performing this move, all skeletal objects (faces, components, etc.) will be reconstructed, which means any pointers to old skeletal objects can no longer be used. However, the arguments e0 and e1 can still be used since a FaceEmbedding can happily outlive the face that it refers to; see the FaceEmbedding class notes for further details.

Precondition
The edge e is an edge of this triangulation.
Parameters
e0an embedding of the common edge e of the two triangles about which to perform the move.
t0indicates one of the triangles about which to perform the move, with respect to the edge embedding e0; this must be 2 or 3.
e1another embedding of the edge e.
t1indicates the other triangle about which to perform the move, with respect to the edge embedding e1; this must be 2 or 3.
Returns
true if and only if the requested move was able to be performed.
Author
Alex He

◆ move02() [3/3]

bool regina::Triangulation< 3 >::move02 ( Triangle< 3 > * t0,
int e0,
Triangle< 3 > * t1,
int e1 )
inline

If possible, performs a 0-2 move about the two specified triangles.

This involves fattening these two triangles (which should share a common edge, and which need not be distinct) into a new pair of tetrahedra surrounding a new degree two edge. This is, in essence, an inverse to the 2-0 edge move.

The different variants of move02() allow the two triangles and their common edge to be specified in different ways. For this variant, the two triangles are given as the arguments t0 and t1, and their common edge is t0->edge(e0) and t1->edge(e1).

This triangulation will be changed directly.

This move will only be performed if it will not change the topology of the manifold (as discussed below), and it will not violate any facet locks. See Simplex<3>::lockFacet() for further details on facet locks. Note that simplex locks are never a concern for this type of move.

To be able to perform this move, we require that:

  • the edges t0->edge(e0) and t1->edge(e1) are the same edge of this triangulation;
  • moreover, that common edge is valid.

A note regarding facet locks: since this move pries open a pair of adjacent triangles and not just a single triangle, a lock on either of the two triangles involved in this move will prevent the move from taking place.

If this triangulation is currently oriented, then this 0-2 move will label the new tetrahedra in a way that preserves the orientation.

The implementation of this routine simply translates its arguments to call move02(EdgeEmbedding<3>, int, EdgeEmbedding<3>, int).

Note that after performing this move, all skeletal objects (faces, components, etc.) will be reconstructed, which means any pointers to old skeletal objects (such as the arguments t0 and t1) can no longer be used.

Precondition
The given triangles are both triangles of this triangulation.
Parameters
t0one of the two triangles about which to perform the move.
e0the edge at which t0 meets the other triangle t1; this must be 0, 1 or 2.
t1the other triangle about which to perform the move.
e1the edge at which t1 meets the other triangle t0; this must be 0, 1 or 2.
Returns
true if and only if the requested move was able to be performed.
Author
Alex He

◆ move20()

bool regina::detail::TriangulationBase< dim >::move20 ( Face< dim, k > * f)
inlineinherited

If possible, performs a 2-0 move about the given k-face of degree two.

This involves taking the two top-dimensional simplices joined along that face and squashing them flat.

This move is currently only implemented for vertices, edges and triangles (i.e., facial dimension k ≤ 2).

This triangulation will be changed directly.

This move will only be performed if it will not change the topology of the manifold (as outlined below), and it will not violate any simplex and/or facet locks. See Simplex<dim>::lock() and Simplex<dim>::lockFacet() for further details on locks.

The requirements for the move to not change the topology depend upon the facial dimension k. In all cases:

  • the face f must be valid and non-boundary, and must have degree 2;
  • the two top-dimensional simplices on either side of f must be distinct;
  • the link of f must be the standard sphere obtained by identifying the boundaries of two (dim - k - 1)-simplices using the identity map;
  • the two (dim - k - 1)-faces opposite f in each top-dimensional simplex must be distinct and not both boundary.

Moreover, there are further requirements depending on the facial dimension k:

  • When performing the move on a vertex (k = 0), there are no additional requirements.
  • When performing the move on an edge (k = 1), there are additional requirements on the (dim - 1)-faces. Specifically: the move would effectively flatten facets f1 and f2 of one top-dimensional simplex onto facets g1 and g2 of the other top-dimensional simplex respectiveyl, and we require that: (a) f1 and g1 are distinct, (b) f2 and g2 are distinct, (c) we do not have both f1 = g2 and g1 = f2, (d) we do not have both f1 = f2 and g1 = g2, and (e) we do not have two of the facets boundary and the other two identified.
  • When performing the move on a triangle (k = 2), there are additional requirements on both the (dim - 1)-faces and the (dim - 2)-faces. These are move involved, and are discussed in detail in the source code for those who are interested.

If this triangulation is currently oriented, then this 2-0 move will preserve the orientation.

Note that after performing this move, all skeletal objects (faces, components, etc.) will be reconstructed, which means any pointers to old skeletal objects (such as the argument f) can no longer be used.

Precondition
The given k-face is a k-face of this triangulation.
Template Parameters
kthe dimension of the given face. This must be 0, 1 or 2, and must not exceed dim - 2.
Parameters
fthe k-face about which to perform the move.
Returns
true if and only if the requested move was able to be performed.

◆ move21()

bool regina::Triangulation< 3 >::move21 ( Edge< 3 > * e,
int edgeEnd )
inline

If possible, performs a 2-1 move at the given end of the given edge of this triangulation.

This involves taking the given degree one edge and effectively merging the (unique) tetrahedron that contains it with an adjacent tetrahedron.

This triangulation will be changed directly.

This move will only be performed if it will not change the topology of the manifold (as discussed below), and it will not violate any simplex and/or facet locks. See Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on locks.

In order for this move to make sense and to not to change the topology, we require that:

  • the given edge e is valid and non-boundary;
  • the given edge e has degree one, whereupon we let t denote the unique tetrahedron containing e;
  • the two faces of t that do not contain e are not joined to each other;
  • the face of t opposite the given endpoint of e is not boundary, whereupon we let f denote this face and we let s denote the adjacent tetrahedron connected to t along f;
  • if we consider the two edges of s that run from (i) the two (identified) vertices of t opposite e to (ii) the vertex of s opposite face f, then these two edges are distinct and not both boundary.

The move essentially flattens two triangular faces of s together, and merges the remnants of s with all of t to form a single new tetrahedron which again is folded onto itself to form a new edge of degree one.

There are additional "distinct and not both boundary" conditions on faces of the second tetrahedron s, but those follow automatically from the final condition above.

If this triangulation is currently oriented, then this 2-1 move will label the new tetrahedra in a way that preserves the orientation.

Note that after performing this move, all skeletal objects (faces, components, etc.) will be reconstructed, which means any pointers to old skeletal objects (such as the argument e) can no longer be used.

Precondition
The given edge is an edge of this triangulation.
Parameters
ethe edge about which to perform the move.
edgeEndthe end of the edge opposite that at which the second tetrahedron (to be merged) is joined. This argument must be 0 or 1, corresponding to the labelling (0,1) of the vertices of the edge as described by EdgeEmbedding<3>::vertices().
Returns
true if and only if the requested move was able to be performed.

◆ move44()

bool regina::Triangulation< 3 >::move44 ( Edge< 3 > * e,
int axis )
inline

If possible, performs a 4-4 move about the given edge of this triangulation.

This involves replacing the four tetrahedra joined along the given degree four edge with four new tetrahedra joined along a different (and new) degree four edge instead.

This triangulation will be changed directly.

This move will only be performed if it will not change the topology of the manifold (as discussed below), and it will not violate any simplex and/or facet locks. See Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on locks.

In order for this move to make sense and to not to change the topology, we require that:

  • the given edge is valid and non-boundary; and
  • the given edge has degree four, and in particular belongs to four distinct tetrahedra.

The move then works as follows. Consider the octahedron made up of the four original tetrahedra. This octahedron has three internal axes: one axis is the given edge, and the other two axes are not represented by edges of the triangulation at all. The move simply retriangulates this octahedron using four new tetrahedra, joined along a new degree four edge that follows one of the other two axes. The argument axis indicates which of these other two axes should be used (as described below).

If this triangulation is currently oriented, then this 4-4 move will label the new tetrahedra in a way that preserves the orientation.

Note that after performing this move, all skeletal objects (faces, components, etc.) will be reconstructed, which means any pointers to old skeletal objects (such as the argument e) can no longer be used.

Precondition
The given edge is an edge of this triangulation.
Parameters
ethe edge about which to perform the move.
axisindicates which axis of the octahedron the four new tetrahedra should meet along; this must be 0 or 1. Specifically: consider the four original tetrahedra in the order described by Edge<3>::embedding(0,...,3); call these tetrahedra 0, 1, 2 and 3. If axis is 0, then the new axis will separate tetrahedra 0 and 1 from 2 and 3. If axis is 1, then the new axis will separate tetrahedra 1 and 2 from 3 and 0.
Returns
true if and only if the requested move was able to be performed.

◆ moveContentsTo()

void regina::detail::TriangulationBase< dim >::moveContentsTo ( Triangulation< dim > & dest)
inherited

Moves the contents of this triangulation into the given destination triangulation, leaving this triangulation empty but otherwise usable.

The top-dimensional simplices of this triangulation will be moved directly into dest, and placed after any pre-existing simplices. Specifically, if the original size of dest was N, then simplex(i) of this triangulation will become dest.simplex(N+i).

This triangulation will become empty as a result, but it will otherwise remain a valid and usable Triangulation object. Any simplex pointers that referred to either this triangulation or dest will remain valid (and will all now refer to dest), though if they originally referred to this triangulation then they will now return different indices. Any locks on top-dimensional simplices and/or their facets will be preserved.

Calling tri.moveContentsTo(dest) is similar to calling dest.insertTriangulation(std::move(tri)); it is a little slower but it comes with the benefit of leaving this triangulation in a usable state.

Precondition
dest is not this triangulation.
Parameters
destthe triangulation into which the contents of this triangulation should be moved.

◆ newSimplex() [1/2]

Simplex< dim > * regina::detail::TriangulationBase< dim >::newSimplex ( )
inherited

Creates a new top-dimensional simplex and adds it to this triangulation.

The new simplex will have an empty description. All (dim+1) facets of the new simplex will be boundary facets.

The new simplex will become the last simplex in this triangulation; that is, it will have index size()-1.

Returns
the new simplex.

◆ newSimplex() [2/2]

Simplex< dim > * regina::detail::TriangulationBase< dim >::newSimplex ( const std::string & desc)
inherited

Creates a new top-dimensional simplex with the given description and adds it to this triangulation.

All (dim+1) facets of the new simplex will be boundary facets.

Descriptions are optional, may have any format, and may be empty. How descriptions are used is entirely up to the user.

The new simplex will become the last simplex in this triangulation; that is, it will have index size()-1.

Parameters
descthe description to give to the new simplex.
Returns
the new simplex.

◆ newSimplexRaw()

Simplex< dim > * regina::detail::TriangulationBase< dim >::newSimplexRaw ( )
inlineprotectedinherited

A variant of newSimplex() with no management of the underlying triangulation.

This routine adjusts the internal list of simplices, just like newSimplex() does. However, this is all it does. In particular:

  • it does not manage the underlying triangulation in any way: it does not take snapshots, fire change events, or clear computed properties.

This should only be used in settings where the other missing tasks such as snapshots, change events and computed properties are being taken care of in some other manner (possibly manually). An example of such a setting might be the implementation of a local move (such as a Pachner move).

Such a "raw" routine would typically be safe to use without any manual error/lock/triangulation management in the following scenarios:

  • triangulation constructors, but only in settings where no properties (including the skeleton) have been computed yet;
  • routines that create a "staging" triangulation, without computing its skeleton or any other properties, and then swap or move this staging triangulation into the triangulation actually being worked upon (see subdivide() for an example).

The return value for this routine is the same as for newSimplex(). See newSimplex() for further details.

◆ newSimplices() [1/2]

std::array< Simplex< dim > *, k > regina::detail::TriangulationBase< dim >::newSimplices ( )
inherited

Creates k new top-dimensional simplices, adds them to this triangulation, and returns them in a std::array.

The main purpose of this routine is to support structured binding; for example:

auto [r, s, t] = ans.newSimplices<3>();
r->join(0, s, {1, 2, 3, 0});
...

All new simplices will have empty descriptions, and all facets of each new simplex will be boundary facets.

The new simplices will become the last k simplices in this triangulation. Specifically, if the return value is the array ret, then each simplex ret[i] will have index size()-k+i in the overall triangulation.

Python
For Python users, the two variants of newSimplices() are essentially merged: the argument k is passed as an ordinary runtime argument, and the new top-dimensional simplices will be returned in a Python tuple of size k.
Template Parameters
kthe number of new top-dimensional simplices to add; this must be non-negative.
Returns
an array containing all of the new simplices, in the order in which they were added.

◆ newSimplices() [2/2]

void regina::detail::TriangulationBase< dim >::newSimplices ( size_t k)
inherited

Creates k new top-dimensional simplices and adds them to this triangulation.

This is similar to the templated routine newSimplices<k>(), but with two key differences:

  • This routine has the disadvantage that it does not return the new top-dimensional simplices, which means you cannot use it with structured binding.
  • This routine has the advantage that k does not need to be known until runtime, which means this routine is accessible to Python users.

All new simplices will have empty descriptions, and all facets of each new simplex will be boundary facets.

The new simplices will become the last k simplices in this triangulation.

Python
For Python users, the two variants of newSimplices() are essentially merged: the argument k is passed as an ordinary runtime argument, and the new top-dimensional simplices will be returned in a Python tuple of size k.
Parameters
kthe number of new top-dimensional simplices to add; this must be non-negative.

◆ newSimplicesRaw()

std::array< Simplex< dim > *, k > regina::detail::TriangulationBase< dim >::newSimplicesRaw ( )
inlineprotectedinherited

A variant of newSimplices() with no lock management, and no management of the underlying triangulation.

See newSimplexRaw() for further details on what these "raw" routines do and where they can be used.

The return value for this routine is the same as for newSimplices(). See newSimplices() for further details.

◆ newTetrahedra() [1/2]

template<int k>
std::array< Tetrahedron< 3 > *, k > regina::Triangulation< 3 >::newTetrahedra ( )
inline

A dimension-specific alias for newSimplices().

See newSimplices() for further information.

◆ newTetrahedra() [2/2]

void regina::Triangulation< 3 >::newTetrahedra ( size_t k)
inline

A dimension-specific alias for newSimplices().

See newSimplices() for further information.

◆ newTetrahedron() [1/2]

Tetrahedron< 3 > * regina::Triangulation< 3 >::newTetrahedron ( )
inline

A dimension-specific alias for newSimplex().

See newSimplex() for further information.

◆ newTetrahedron() [2/2]

Tetrahedron< 3 > * regina::Triangulation< 3 >::newTetrahedron ( const std::string & desc)
inline

A dimension-specific alias for newSimplex().

See newSimplex() for further information.

◆ niceTreeDecomposition()

const TreeDecomposition & regina::Triangulation< 3 >::niceTreeDecomposition ( ) const
inline

Returns a nice tree decomposition of the face pairing graph of this triangulation.

This can (for example) be used in implementing algorithms that are fixed-parameter tractable in the treewidth of the face pairing graph.

See TreeDecomposition for further details on tree decompositions, and see TreeDecomposition::makeNice() for details on what it means to be a nice tree decomposition.

This routine is fast: it will use a greedy algorithm to find a tree decomposition with (hopefully) small width, but with no guarantees that the width of this tree decomposition is the smallest possible.

The tree decomposition will be cached, so that if this routine is called a second time (and the underlying triangulation has not been changed) then the same tree decomposition will be returned immediately.

Returns
a nice tree decomposition of the face pairing graph of this triangulation.

◆ nonTrivialSphereOrDisc()

std::optional< NormalSurface > regina::Triangulation< 3 >::nonTrivialSphereOrDisc ( ) const

Searches for a non-vertex-linking normal sphere or disc within this triangulation.

If such a surface exists within this triangulation, this routine is guaranteed to find one.

Returns
a non-vertex-linking normal sphere or disc, or no value if none exists.

◆ octagonalAlmostNormalSphere()

std::optional< NormalSurface > regina::Triangulation< 3 >::octagonalAlmostNormalSphere ( ) const

Searches for an octagonal almost normal 2-sphere within this triangulation.

If such a surface exists, this routine is guaranteed to find one.

Precondition
This triangulation is valid, closed, orientable, connected, and 0-efficient. These preconditions are almost certainly more restrictive than they need to be, but we stay safe for now.
Returns
an octagonal almost normal 2-sphere, or no value if none exists.

◆ openBook() [1/2]

bool regina::Triangulation< 3 >::openBook ( Triangle< 3 > * t)
inline

If possible, performs a book opening move about the given triangle.

This involves taking a triangle that meets the boundary along precisely two edges, and ungluing it to create two new boundary triangles. The resulting effect is to expose the tetrahedra it initially joined, and hopefully open the way for subsequent boundary shelling moves.

This triangulation will be changed directly.

This move will only be performed if it will not change the topology of the manifold (as discussed below), and it will not violate any facet locks. See Simplex<3>::lockFacet() for further details on facet locks. Note that simplex locks are never a concern for this type of move.

In order to not change the topology, we impose the following requirements:

  • the given triangle meets the boundary in precisely two edges (and therefore also joins two tetrahedra;
  • the vertex between these two edges is a standard boundary vertex (i.e., its link is a disc);
  • the remaining edge of the triangle (which is internal to the triangulation) is valid.

Whilst we do not (currently) support the case where the given triangle meets the boundary in just one edge, those triangulations that we miss out on can typically be simplified in other ways (since they would typically have spurious internal vertices).

If this triangulation is currently oriented, then this operation will (trivially) preserve the orientation.

Note that after performing this move, all skeletal objects (faces, components, etc.) will be reconstructed, which means any pointers to old skeletal objects (such as the argument t) can no longer be used.

See closeBook() for an inverse to this move.

Precondition
The given triangle is a triangle of this triangulation.
Parameters
tthe triangle about which to perform the move.
Returns
true if and only if the requested move was able to be performed.

◆ openBook() [2/2]

bool regina::Triangulation< 3 >::openBook ( Triangle< 3 > * t,
bool ignored,
bool perform = true )
inline

Deprecated routine that tests for and optionally performs a book opening move about the given triangle of this triangulation.

For more details on book opening moves and when they can be performed, see the variant of openBook() without the extra boolean arguments.

This routine will always check whether the requested move is legal and will not violate any facet locks (see Simplex<3>::lockFacet() for further details on facet locks). Note that this type of move can never violate a simplex lock, and so there is no need to check for those at all. If the move is allowed, and if the argument perform is true, this routine will also perform the move.

Deprecated
If you just wish to test whether such a move is possible, call hasOpenBook(). If you wish to both check and perform the move, call openBook() without the two extra boolean arguments.
Precondition
The given triangle is a triangle of this triangulation.
Parameters
tthe triangle about which to perform the move.
ignoredan argument that is ignored. In earlier versions of Regina this argument controlled whether we check if the move can be performed; however, now this check is done always.
performtrue if we should actually perform the move, assuming the move is allowed.
Returns
true if and only if the requested move could be performed.

◆ operator=() [1/2]

Triangulation< 3 > & regina::Triangulation< 3 >::operator= ( const Triangulation< 3 > & src)
inline

Sets this to be a (deep) copy of the given triangulation.

This will also clone any computed properties (such as homology, fundamental group, and so on), as well as the skeleton (vertices, edges, components, etc.). In particular, this triangulation will use the same numbering and labelling for all skeletal objects as in the source triangulation.

If src has any locks on top-dimensional simplices and/or their facets, these locks will also be copied across.

Parameters
srcthe triangulation to copy.
Returns
a reference to this triangulation.

◆ operator=() [2/2]

Triangulation< 3 > & regina::Triangulation< 3 >::operator= ( Triangulation< 3 > && src)
inline

Moves the contents of the given triangulation into this triangulation.

This is much faster than copy assignment, but is still linear time. This is because every tetrahedron must be adjusted to point back to this triangulation instead of src.

All tetrahedra and skeletal objects (faces, components and boundary components) that belong to src will be moved into this triangulation, and so any pointers or references to Tetrahedron<3>, Face<3, subdim>, Component<3> or BoundaryComponent<3> objects will remain valid. Likewise, all cached properties will be moved into this triangulation.

If src has any locks on top-dimensional simplices and/or their facets, these locks will also be moved across.

The triangulation that is passed (src) will no longer be usable.

Note
This operator is not marked noexcept, since it fires change events on this triangulation which may in turn call arbitrary code via any registered packet listeners. It deliberately does not fire change events on src, since it assumes that src is about to be destroyed (which will fire a destruction event instead).
Parameters
srcthe triangulation to move.
Returns
a reference to this triangulation.

◆ operator==()

bool regina::detail::TriangulationBase< dim >::operator== ( const TriangulationBase< dim > & other) const
inherited

Determines if this triangulation is combinatorially identical to the given triangulation.

Here "identical" means that the triangulations have the same number of top-dimensional simplices, with gluings between the same pairs of numbered simplices using the same gluing permutations. In other words, "identical" means that the triangulations are isomorphic via the identity isomorphism.

For the less strict notion of isomorphic triangulations, which allows relabelling of the top-dimensional simplices and their vertices, see isIsomorphicTo() instead.

This test does not examine the textual simplex descriptions or simplex/facet locks, as seen in Simplex<dim>::description() and Simplex<dim>::lockMask(); these may still differ. It also does not test whether lower-dimensional faces are numbered identically (vertices, edges and so on); this routine is only concerned with top-dimensional simplices.

(At the time of writing, two identical triangulations will always number their lower-dimensional faces in the same way. However, it is conceivable that in future versions of Regina there may be situations in which identical triangulations can acquire different numberings for vertices, edges, and so on.)

In Regina 6.0.1 and earlier, this comparison was called isIdenticalTo().

Parameters
otherthe triangulation to compare with this.
Returns
true if and only if the two triangulations are combinatorially identical.

◆ order()

bool regina::Triangulation< 3 >::order ( bool forceOriented = false)

Relabels tetrahedron vertices in this triangulation to give an ordered triangulation, if possible.

To be an ordered triangulation, all face gluings (when restricted to the tetrahedron face) must be order preserving. In other words, it must be possible to orient all edges of the triangulation in such a fashion that they are consistent with the ordering of the vertices in each tetrahedron.

If it is possible to order this triangulation, the vertices of each tetrahedron will be relabelled accordingly and this routine will return true. Otherwise, this routine will return false and the triangulation will not be changed.

If this triangulation has locks on any tetrahedra and/or their facets, these will not prevent the ordering from taking place. Instead, any locks will be transformed accordingly (i.e., the facets of each tetrahedron will exchange their lock states according to how the vertices of that tetrahedron have been relabelled).

Warning
This routine may be slow, since it backtracks through all possible edge orientations until a consistent one has been found.
Precondition
This triangulation is valid.
Parameters
forceOrientedtrue if the triangulation must be both ordered and oriented, in which case this routine will return false if the triangulation cannot be oriented and ordered at the same time. See orient() for further details.
Returns
true if the triangulation has been successfully ordered as described above, or false if not.
Exceptions
FailedPreconditionThis triangulation is invalid.
Author
Matthias Goerner

◆ orient()

void regina::detail::TriangulationBase< dim >::orient ( )
inherited

Relabels the vertices of top-dimensional simplices in this triangulation so that all simplices are oriented consistently, if possible.

This routine works by flipping vertices (dim - 1) and dim of each top-dimensional simplex that has negative orientation. The result will be a triangulation where the top-dimensional simplices have their vertices labelled in a way that preserves orientation across adjacent facets. In particular, every gluing permutation will have negative sign.

If this triangulation includes both orientable and non-orientable components, the orientable components will be oriented as described above and the non-orientable components will be left untouched.

If this triangulation has locks on any top-dimensional simplices and/or their facets, these will not prevent the orientation from taking place. Instead, any locks will be transformed accordingly (i.e., facets (dim - 1) and dim will exchange their lock states for those simplices that originally had negative orientation).

◆ pachner() [1/3]

bool regina::detail::TriangulationBase< dim >::pachner ( Face< dim, k > * f)
inlineinherited

If possible, performs a (dim + 1 - k)-(k + 1) Pachner move about the given k-face.

This involves replacing the (dim + 1 - k) top-dimensional simplices meeting that k-face with (k + 1) new top-dimensional simplices joined along a new internal (dim - k)-face.

This triangulation will be changed directly.

This move will only be performed if it will not change the topology of the manifold (as outlined below), and it will not violate any simplex and/or facet locks. See Simplex<dim>::lock() and Simplex<dim>::lockFacet() for further details on locks.

In order to not change the topology, we require that:

  • the given k-face is valid and non-boundary;
  • the (dim + 1 - k) top-dimensional simplices that contain it are distinct; and
  • these simplices are joined in such a way that the link of the given k-face is the standard triangulation of the (dim - 1 - k)-sphere as the boundary of a (dim - k)-simplex.

If this triangulation is currently oriented, then this Pachner move will label the new top-dimensional simplices in a way that preserves the orientation.

Note that after performing this move, all skeletal objects (faces, components, etc.) will be reconstructed, which means any pointers to old skeletal objects (such as the argument f) can no longer be used.

See the page on Pachner moves on triangulations for definitions and terminology relating to Pachner moves. After the move, the new belt face will be formed from vertices 0,1,...,(dim - k) of simplices().back().

Warning
The check for this move takes quadratic time in the number of top-dimensional simplices involved (which may become expensive when dim is large and k is small). If you are certain that the move is legal, and you wish to circumvent this check, C++ users can call the variant of this function that takes an extra Unprotected argument.
For the case k = dim in Regina's standard dimensions, the labelling of the belt face has changed as of Regina 5.96 (the first prerelease for Regina 6.0). In versions 5.1 and earlier, the belt face was simplices().back()->vertex(dim), and as of version 5.96 it is now simplices().back()->vertex(0).
Precondition
The given k-face is a k-face of this triangulation.
Template Parameters
kthe dimension of the given face. This must be between 0 and (dim) inclusive.
Parameters
fthe k-face about which to perform the move.
Returns
true if and only if the requested move was able to be performed.

◆ pachner() [2/3]

bool regina::detail::TriangulationBase< dim >::pachner ( Face< dim, k > * f,
bool ignored,
bool perform = true )
inlineinherited

Deprecated routine that tests for and optionally performs a (dim + 1 - k)-(k + 1) Pachner move about the given k-face of this triangulation.

For more detail on Pachner moves and when they can be performed, see the variant of pachner() without the extra boolean arguments.

This routine will always check whether the requested move is legal and will not violate any simplex and/or facet locks (see Simplex<dim>::lock() and Simplex<dim>::lockFacet() for further details on locks). If the move is allowed, and if the argument perform is true, this routine will also perform the move.

Deprecated
If you just wish to test whether such a move is possible, call hasPachner(). If you wish to both check and perform the move, call pachner() without the two extra boolean arguments.
Precondition
The given k-face is a k-face of this triangulation.
Template Parameters
kthe dimension of the given face. This must be between 0 and (dim) inclusive.
Parameters
fthe k-face about which to perform the move.
ignoredan argument that is ignored. In earlier versions of Regina this argument controlled whether we check if the move can be performed; however, now this check is done always.
performtrue if we should actually perform the move, assuming the move is allowed.
Returns
true if and only if the requested move could be performed.

◆ pachner() [3/3]

void regina::detail::TriangulationBase< dim >::pachner ( Face< dim, k > * f,
Unprotected  )
inlineinherited

Performs a (dim + 1 - k)-(k + 1) Pachner move about the given k-face, without any safety checks.

This variant of pachner() is offered because it can become expensive to test whether a Pachner move can be performed on a given face when dim is large and k is small (and therefore there are many top-dimensional simplices involved in the move).

This function will always perform the requested Pachner move directy on this triangulation, without first testing whether it is legal. The onus is on the programmer to ensure the legality of the move beforehand. Getting this wrong could be disastrous: you could change the topology of the manifold, or possibly end up with an invalid triangulation, or this function could throw an exception if you attempt to violate a simplex and/or facet lock.

The (unnamed) Unprotected argument would typically be the constant regina::unprotected.

For more detail on Pachner moves and when they can be performed, see the variant of pachner() that does not take an extra Unprotected argument.

Precondition
The given k-face is a k-face of this triangulation.
Python
Not present. By design, Python users are not able to circumvent the legality checks for Pachner moves. If speed is essential, you should be using C++.
Exceptions
LockViolationThis move would violate a simplex or facet lock. This exception will be thrown before any changes are made.
Template Parameters
kthe dimension of the given face. This must be between 0 and (dim) inclusive.
Parameters
fthe k-face about which to perform the move.

◆ packet() [1/2]

std::shared_ptr< PacketOf< Triangulation< dim > > > regina::PacketData< Triangulation< dim > >::packet ( )
inlineinherited

Returns the packet that holds this data, if there is one.

If this object is being held by a packet p of type PacketOf<Held>, then that packet p will be returned. Otherwise, if this is a "standalone" object of type Held, then this routine will return null.

There is a special case when dealing with a packet q that holds a SnapPea triangulation. Here q is of type PacketOf<SnapPeaTriangulation>, and it holds a Triangulation<3> "indirectly" in the sense that Packetof<SnapPeaTriangulation> derives from SnapPeaTriangulation, which in turn derives from Triangulation<3>. In this scenario:

The function inAnyPacket() is specific to Triangulation<3>, and is not offered for other Held types.

Returns
the packet that holds this data, or null if this data is not (directly) held by a packet.

◆ packet() [2/2]

std::shared_ptr< const PacketOf< Triangulation< dim > > > regina::PacketData< Triangulation< dim > >::packet ( ) const
inlineinherited

Returns the packet that holds this data, if there is one.

See the non-const version of this function for further details, and in particular for how this functions operations in the special case of a packet that holds a SnapPea triangulation.

Returns
the packet that holds this data, or null if this data is not (directly) held by a packet.

◆ pairing()

FacetPairing< dim > regina::detail::TriangulationBase< dim >::pairing ( ) const
inlineinherited

Returns the dual graph of this triangulation, expressed as a facet pairing.

Calling tri.pairing() is equivalent to calling FacetPairing<dim>(tri).

Precondition
This triangulation is not empty.
Returns
the dual graph of this triangulation.

◆ pentachora()

auto regina::detail::TriangulationBase< dim >::pentachora ( ) const
inlineinherited

A dimension-specific alias for faces<4>(), or an alias for simplices() in dimension dim = 4.

This alias is available for dimensions dim ≥ 4.

See faces() for further information.

◆ pentachoron() [1/2]

auto regina::detail::TriangulationBase< dim >::pentachoron ( size_t index)
inlineinherited

A dimension-specific alias for face<4>(), or an alias for simplex() in dimension dim = 4.

This alias is available for dimensions dim ≥ 4. It returns a non-const pentachoron pointer.

See face() for further information.

◆ pentachoron() [2/2]

auto regina::detail::TriangulationBase< dim >::pentachoron ( size_t index) const
inlineinherited

A dimension-specific alias for face<4>(), or an alias for simplex() in dimension dim = 4.

This alias is available for dimensions dim ≥ 4. It returns a const pentachoron pointer in dimension dim = 4, and a non-const pentachoron pointer in all higher dimensions.

See face() for further information.

◆ pinchEdge()

void regina::Triangulation< 3 >::pinchEdge ( Edge< 3 > * e)

Pinches an internal edge to a point.

Topologically, this collapses the edge to a point with no further side-effects, and it increases the number of tetrahedra by two.

This operation can be performed on any internal edge, without further constraints. Two particularly useful settings are:

  • If the edge joins an internal vertex with some different vertex (which may be internal, boundary, ideal or invalid), then this move does not change the topology of the manifold at all, and it reduces the total number of vertices by one. In this sense, it acts as an alternative to collapseEdge(), and unlike collapseEdge() it can always be performed.
  • If the edge runs from an internal vertex back to itself, then this move effectively drills out the edge, leaving an ideal torus or Klein bottle boundary component.

We do not allow e to lie entirely on the triangulation boundary, because the implementation actually collapses an internal curve parallel to e, not the edge e itself (and so if e is a boundary edge then the topological effect would not be as intended). We do allow e to be an internal edge with both endpoints on the boundary, but note that in this case the resulting topological operation would render the triangulation invalid.

If you are trying to reduce the number of vertices without changing the topology, and if e is an edge connecting an internal vertex with some different vertex, then either collapseEdge() or pinchEdge() may be more appropriate for your situation (though you may find it easier just to call minimiseVertices() instead).

  • The advantage of collapseEdge() is that it decreases the number of tetrahedra, whereas pinchEdge() increases this number (but only by two).
  • The disadvantages of collapseEdge() are that it cannot always be performed, and its validity tests are expensive; pinchEdge() on the other hand can always be used for edges e of the type described above.

This operation works by prying open a triangle t and inserting a two-tetrahedron gadget g within the resulting triangular pillow. In particular, this means that simplex and/or facet locks will never prevent this operation from taking place: if the triangle t happens to be locked, then this lock will simply move across to one of the two triangles bounding the gadget g.

If this triangulation is currently oriented, then this operation will preserve the orientation.

Note that after performing this move, all skeletal objects (triangles, components, etc.) will be reconstructed, which means any pointers to old skeletal objects (such as the argument e) can no longer be used.

Precondition
The given edge is an internal edge of this triangulation (that is, e does not lie entirely within the boundary).
Exceptions
InvalidArgumentThe given edge lies entirely within the boundary of the triangulation.
Parameters
ethe edge to collapse.

◆ puncture() [1/2]

void regina::Triangulation< 3 >::puncture ( Tetrahedron< 3 > * tet)
inline

Deprecated routine that punctures this manifold by removing a 3-ball from the interior of the given tetrahedron.

Deprecated
Since the operation in fact involves prying open a triangle, puncture() now takes a triangle instead of a tetrahedron to indicate the location for the operation. If tet is null, then this function is equivalent to calling puncture(); otherwise it is equivalent to calling puncture(tet->triangle(0)). See puncture(Triangle<3>*) for further details.
Precondition
This triangulation is non-empty, and if tet is non-null then it is in fact a tetrahedron of this triangulation.
Exceptions
InvalidArgumentThe given tetrahedron is non-null but not a tetrahedron of this triangulation, or the given tetrahedron is null but this triangulation is empty.
Parameters
tetthe tetrahedron indicating where the puncture will be taken. This may be null, in which case tetrahedron 0 will be used.

◆ puncture() [2/2]

void regina::Triangulation< 3 >::puncture ( Triangle< 3 > * location = nullptr)

Punctures this manifold by thickening the given triangle into a triangular pillow and then removing a 3-ball from its interior.

If no triangle is specified (i.e., the triangle pointer is null), then the triangle used will be facet 0 of tetrahedron 0.

The puncture will not meet the boundary of the pillow, and so nothing will go wrong if the given triangle is boundary or has ideal vertices. A side-effect of this, however, is that the resulting triangulation will contain additional vertices, and will almost certainly be far from minimal. It is highly recommended that you run simplify() if you do not need to preserve the combinatorial structure of the new triangulation.

If this triangulation is currently oriented, then this operation will preserve the orientation.

The new sphere boundary will be formed from two triangles; specifically, face 0 of the last and second-last tetrahedra of the triangulation. These two triangles will be joined so that vertex 1 of each tetrahedron coincides, and vertices 2,3 of one map to vertices 3,2 of the other.

Tetrahedron and/or facet locks will not prevent the puncture from taking place. If the given triangle was locked, then this lock will be moved to one of the two triangles surrounding the triangular pillow. In particular, if the given triangle is boundary, then the lock will be moved to the corresponding boundary triangle.

Precondition
This triangulation is non-empty, and if location is non-null then it is in fact a triangle belonging to this triangulation.
Exceptions
InvalidArgumentThe given triangle is non-null but not a triangle of this triangulation, or the given triangle is null but this triangulation is empty.
Parameters
locationthe triangle indicating where the puncture should be taken. This may be null (the default), in which case facet 0 of tetrahedron 0 will be used.

◆ randomiseLabelling()

Isomorphism< dim > regina::detail::TriangulationBase< dim >::randomiseLabelling ( bool preserveOrientation = true)
inlineinherited

Randomly relabels the top-dimensional simplices and their vertices.

Essentially, this routine creates a random isomorphism of the correct size and applies it in-place to this triangulation.

The advantage of using this routine instead of working directly through the Isomorphism class is that this routine preserves any computed topological properties of the triangulation (as opposed to the isomorphism bracket operator, which at the time of writing does not).

Parameters
preserveOrientationif true, then every top-dimensional simplex will have its vertices permuted with an even permutation. This means that, if this triangulation is oriented, then randomiseLabelling() will preserve the orientation.
Returns
the random isomorphism that was applied; that is, the isomorphism from the original triangulation to the final triangulation.

◆ recogniseHandlebody()

ssize_t regina::Triangulation< 3 >::recogniseHandlebody ( ) const

Determines whether this is a triangulation of an orientable handlebody, and if so, which genus.

Specifically, this routine returns the genus if this is indeed a handlebody, and returns -1 otherwise. This routine can be used on a triangulation with real boundary triangles, or on an ideal triangulation (in which case all ideal vertices will be assumed to be truncated).

Warning
The algorithms used in this routine rely on normal surface theory and so might be very slow for larger triangulations (although faster tests are used where possible). The routine knowsHandlebody() can be called to see if this property is already known or if it happens to be very fast to calculate for this triangulation.
Returns
the genus if this is a triangulation of an orientable handlebody, or -1 otherwise.
Author
Alex He

◆ recogniser() [1/2]

std::string regina::Triangulation< 3 >::recogniser ( ) const

Returns a string that expresses this triangulation in Matveev's 3-manifold recogniser format.

Recogniser exports are currently not available for triangulations that are invalid or contain boundary triangles. If either of these conditions is true then this routine will throw an exception.

Exceptions
NotImplementedThis triangulation is either invalid or has boundary triangles.
Returns
a string containing the 3-manifold recogniser data.

◆ recogniser() [2/2]

void regina::Triangulation< 3 >::recogniser ( std::ostream & out) const

Writes a string expressing this triangulation in Matveev's 3-manifold recogniser format to the given output stream.

Recogniser exports are currently not available for triangulations that are invalid or contain boundary triangles. If either of these conditions is true then this routine will throw an exception.

Exceptions
NotImplementedThis triangulation is either invalid or has boundary triangles.
Python
Not present. Instead call recogniser() with no arguments, which returns this data as a string.
Parameters
outthe output stream to which the recogniser data file will be written.

◆ recognizer() [1/2]

std::string regina::Triangulation< 3 >::recognizer ( ) const

A synonym for recogniser().

This returns a string that expresses this triangulation in Matveev's 3-manifold recogniser format.

Recogniser exports are currently not available for triangulations that are invalid or contain boundary triangles. If either of these conditions is true then this routine will throw an exception.

Exceptions
NotImplementedThis triangulation is either invalid or has boundary triangles.
Returns
a string containing the 3-manifold recogniser data.

◆ recognizer() [2/2]

void regina::Triangulation< 3 >::recognizer ( std::ostream & out) const
inline

A synonym for recognizer(std::ostream&).

This writes a string expressing this triangulation in Matveev's 3-manifold recogniser format to the given output stream.

Recogniser exports are currently not available for triangulations that are invalid or contain boundary triangles. If either of these conditions is true then this routine will throw an exception.

Exceptions
NotImplementedThis triangulation is either invalid or has boundary triangles.
Python
Not present. Instead call recognizer() with no arguments, which returns this data as a string.
Parameters
outthe output stream to which the recogniser data file will be written.

◆ reflect()

void regina::detail::TriangulationBase< dim >::reflect ( )
inherited

Relabels the vertices of top-dimensional simplices in this triangulation so that all simplices reflect their orientation.

In particular, if this triangulation is oriented, then it will be converted into an isomorphic triangulation with the opposite orientation.

This routine works by flipping vertices (dim - 1) and dim of every top-dimensional simplex.

If this triangulation has locks on any top-dimensional simplices and/or their facets, these will not prevent the reflection from taking place. Instead, any locks will be transformed accordingly (i.e., facets (dim - 1) and dim will exchange their lock states in every top-dimensional simplex).

◆ rehydrate()

static Triangulation< 3 > regina::Triangulation< 3 >::rehydrate ( const std::string & dehydration)
static

Rehydrates the given alphabetical string into a 3-dimensional triangulation.

For a full description of the dehydrated triangulation format, see A Census of Cusped Hyperbolic 3-Manifolds, Callahan, Hildebrand and Weeks, Mathematics of Computation 68/225, 1999.

The converse routine dehydrate() can be used to extract a dehydration string from an existing triangulation. Dehydration followed by rehydration might not produce a triangulation identical to the original, but it is guaranteed to produce an isomorphic copy. See dehydrate() for the reasons behind this.

Exceptions
InvalidArgumentThe given string could not be rehydrated.
Parameters
dehydrationa dehydrated representation of the triangulation to construct. Case is irrelevant; all letters will be treated as if they were lower case.
Returns
the rehydrated triangulation.

◆ removeAllSimplices()

void regina::detail::TriangulationBase< dim >::removeAllSimplices ( )
inlineinherited

Removes all simplices from the triangulation.

As a result, this triangulation will become empty.

All of the simplices that belong to this triangulation will be destroyed immediately.

Exceptions
LockViolationThis triangulation contains at least one locked top-dimensional simplex and/or facet. This exception will be thrown before any changes are made. See Simplex<dim>::lock() and Simplex<dim>::lockFacet() for further details on how such locks work and what their implications are.

◆ removeAllTetrahedra()

void regina::Triangulation< 3 >::removeAllTetrahedra ( )
inline

A dimension-specific alias for removeAllSimplices().

See removeAllSimplices() for further information.

Exceptions
LockViolationThis triangulation contains at least one locked tetrahedron and/or facet. This exception will be thrown before any changes are made. See Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on how such locks work and what their implications are.

◆ removeSimplex()

void regina::detail::TriangulationBase< dim >::removeSimplex ( Simplex< dim > * simplex)
inlineinherited

Removes the given top-dimensional simplex from this triangulation.

The given simplex will be unglued from any adjacent simplices (if any), and will be destroyed immediately.

Precondition
The given simplex is a top-dimensional simplex in this triangulation.
Exceptions
LockViolationThe given simplex and/or one of its facets is currently locked. This exception will be thrown before any changes are made. See Simplex<dim>::lock() and Simplex<dim>::lockFacet() for further details on how such locks work and what their implications are.
Parameters
simplexthe simplex to remove.

◆ removeSimplexAt()

void regina::detail::TriangulationBase< dim >::removeSimplexAt ( size_t index)
inlineinherited

Removes the top-dimensional simplex at the given index in this triangulation.

This is equivalent to calling removeSimplex(simplex(index)).

The given simplex will be unglued from any adjacent simplices (if any), and will be destroyed immediately.

Exceptions
LockViolationThe requested simplex and/or one of its facets is currently locked. This exception will be thrown before any changes are made. See Simplex<dim>::lock() and Simplex<dim>::lockFacet() for further details on how such locks work and what their implications are.
Parameters
indexspecifies which top-dimensional simplex to remove; this must be between 0 and size()-1 inclusive.

◆ removeSimplexRaw()

void regina::detail::TriangulationBase< dim >::removeSimplexRaw ( Simplex< dim > * simplex)
inlineprotectedinherited

A variant of removeSimplex() with no lock management, and no management of the underlying triangulation.

See newSimplexRaw() for further details on what these "raw" routines do and where they can be used.

The arguments for this routine are the same as for removeSimplex(). See removeSimplex() for further details.

◆ removeTetrahedron()

void regina::Triangulation< 3 >::removeTetrahedron ( Tetrahedron< 3 > * tet)
inline

A dimension-specific alias for removeSimplex().

See removeSimplex() for further information.

Exceptions
LockViolationThe given tetrahedron and/or one of its facets is currently locked. This exception will be thrown before any changes are made. See Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on how such locks work and what their implications are.
Parameters
tetthe tetrahedron to remove.

◆ removeTetrahedronAt()

void regina::Triangulation< 3 >::removeTetrahedronAt ( size_t index)
inline

A dimension-specific alias for removeSimplexAt().

See removeSimplexAt() for further information.

Exceptions
LockViolationThe requested tetrahedron and/or one of its facets is currently locked. This exception will be thrown before any changes are made. See Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on how such locks work and what their implications are.
Parameters
indexspecifies which tetrahedron to remove; this must be between 0 and size()-1 inclusive.

◆ reorderBFS()

void regina::detail::TriangulationBase< dim >::reorderBFS ( bool reverse = false)
inherited

Reorders the top-dimensional simplices of this triangulation using a breadth-first search, so that small-numbered simplices are adjacent to other small-numbered simplices.

Specifically, the reordering will operate as follows. Simplex 0 will remain simplex 0. Its immediate neighbours will be numbered 1,2,...,(dim+1) (though if these neighbours are not distinct then of course fewer labels will be required). Their immediate neighbours will in turn be numbered (dim+2), (dim+3) and so on, ultimately following a breadth-first search throughout the entire triangulation.

If the optional argument reverse is true, then simplex numbers will be assigned in reverse order. That is, simplex 0 will become simplex n-1, its immediate neighbours will become simplices n-2, n-3, etc., and so on.

If this triangulation has locks on any top-dimensional simplices and/or their facets, these will not prevent the reordering from taking place. Instead, any locks will be transformed accordingly; that is, all top-dimensional simplices will carry their own locks and their facets' locks around with them as they are reordered.

Parameters
reversetrue if the new simplex numbers should be assigned in reverse order, as described above.

◆ reorderTetrahedraBFS()

void regina::Triangulation< 3 >::reorderTetrahedraBFS ( bool reverse = false)
inline

Deprecated alias for reorderBFS(), which reorders the tetrahedra of this triangulation using a breadth-first search.

Deprecated
This routine has been renamed reorderBFS() (and is now available for triangulations in all dimension). See reorderBFS() for further details.
Parameters
reversetrue if the new tetrahedron numbers should be assigned in reverse order, as described above.

◆ retriangulate()

template<typename Action , typename... Args>
bool regina::Triangulation< 3 >::retriangulate ( int height,
int threads,
ProgressTrackerOpen * tracker,
Action && action,
Args &&... args ) const
inline

Explores all triangulations that can be reached from this via Pachner moves, without exceeding a given number of additional tetrahedra.

Specifically, this routine will iterate through all triangulations that can be reached from this triangulation via 2-3 and 3-2 Pachner moves, without ever exceeding height additional tetrahedra beyond the original number, and without violating any simplex and/or facet locks.

For every such triangulation (including this starting triangulation), this routine will call action (which must be a function or some other callable object).

  • action must take the following initial argument(s). Either (a) the first argument must be a triangulation (the precise type is discussed below), representing the triangluation that has been found; or else (b) the first two arguments must be of types const std::string& followed by a triangulation, representing both the triangulation and an isomorphism signature. The second form is offered in order to avoid unnecessary recomputation within the action function; however, note that the signature might not be of the IsoSigClassic type (i.e., it might not match the output from the default version of isoSig()). If there are any additional arguments supplied in the list args, then these will be passed as subsequent arguments to action.
  • The triangulation argument will be passed as an rvalue; a typical action could (for example) take it by const reference and query it, or take it by value and modify it, or take it by rvalue reference and move it into more permanent storage.
  • action must return a boolean. If action ever returns true, then this indicates that processing should stop immediately (i.e., no more triangulations will be processed).
  • action may, if it chooses, make changes to this triangulation (i.e., the original triangulation upon which retriangulate() was called). This will not affect the search: all triangulations that this routine visits will be obtained via Pachner moves from the original form of this triangulation, before any subsequent changes (if any) were made.
  • action will only be called once for each triangulation (including this starting triangulation). In other words, no triangulation will be revisited a second time in a single call to retriangulate().

This routine can be very slow and very memory-intensive, since the number of triangulations it visits may be superexponential in the number of tetrahedra, and it records every triangulation that it visits (so as to avoid revisiting the same triangulation again). It is highly recommended that you begin with height = 1, and if necessary try increasing height one at a time until this routine becomes too expensive to run.

If height is negative, then there will be no bound on the number of additional tetrahedra. This means that the routine will never terminate, unless action returns true for some triangulation that is passed to it (or unless there are so many locks that the number of reachable triangulations becomes finite).

If any tetrahedra and/or triangles are locked, these locks will be respected: that is, the retriangulation will avoid any moves that would violate these locks (and in particular, no LockViolation exceptions should be thrown). Of course, however, having locks may reduce the number of distinct triangulations that can be reached.

Since Regina 7.0, this routine will not return until the exploration of triangulations is complete, regardless of whether a progress tracker was passed. If you need the old behaviour (where passing a progress tracker caused the enumeration to start in the background), simply call this routine in a new detached thread.

To assist with performance, this routine can run in parallel (multithreaded) mode; simply pass the number of parallel threads in the argument threads. Even in multithreaded mode, this routine will not return until processing has finished (i.e., either action returned true, or the search was exhausted). All calls to action will be protected by a mutex (i.e., different threads will never be calling action at the same time); as a corollary, the action should avoid expensive operations where possible (otherwise it will become a serialisation bottleneck in the multithreading).

Precondition
This triangulation is connected.
Exceptions
FailedPreconditionThis triangulation has more than one connected component. If a progress tracker was passed, it will be marked as finished before the exception is thrown.
Warning
The API for this class or function has not yet been finalised. This means that the interface may change in new versions of Regina, without maintaining backward compatibility. If you use this class directly in your own code, please check the detailed changelog with each new release to see if you need to make changes to your code.
Python
This function is available in Python, and the action argument may be a pure Python function. However, its form is more restricted: the arguments tracker and args are removed, so you call it as retriangulate(height, threads, action). Moreover, action must take exactly two arguments (const std::string&, Triangulation<3>&&) representing a signature and the triangulation, as described in option (b) above.
Parameters
heightthe maximum number of additional tetrahedra to allow beyond the number of tetrahedra originally present in the triangulation, or a negative number if this should not be bounded.
threadsthe number of threads to use. If this is 1 or smaller then the routine will run single-threaded.
trackera progress tracker through which progress will be reported, or null if no progress reporting is required.
actiona function (or other callable object) to call for each triangulation that is found.
argsany additional arguments that should be passed to action, following the initial triangulation argument(s).
Returns
true if some call to action returned true (thereby terminating the search early), or false if the search ran to completion.

◆ saveRecogniser()

bool regina::Triangulation< 3 >::saveRecogniser ( const char * filename) const

Writes this triangulation to the given file in Matveev's 3-manifold recogniser format.

Recogniser exports are currently not available for triangulations that are invalid or contain boundary triangles. If either of these conditions is true then the file will not be written, and this routine will return false.

Internationalisation
This routine makes no assumptions about the character encoding used in the given file name, and simply passes it through unchanged to low-level C/C++ file I/O routines. The contents of the file will be written using UTF-8.
Parameters
filenamethe name of the Recogniser file to which to write.
Returns
true if and only if the file was successfully written.

◆ saveRecognizer()

bool regina::Triangulation< 3 >::saveRecognizer ( const char * filename) const
inline

A synonym for saveRecogniser().

This writes this triangulation to the given file in Matveev's 3-manifold recogniser format.

Precondition
This triangulation is not invalid, and does not contain any boundary triangles.
Internationalisation
This routine makes no assumptions about the character encoding used in the given file name, and simply passes it through unchanged to low-level C/C++ file I/O routines. The contents of the file will be written using UTF-8.
Parameters
filenamethe name of the Recogniser file to which to write.
Returns
true if and only if the file was successfully written.

◆ saveSnapPea()

bool regina::Triangulation< 3 >::saveSnapPea ( const char * filename) const

Writes this triangulation to the given file using SnapPea's native file format.

Regarding what gets stored in the SnapPea data file:

  • Since this function is defined by Regina's own Triangulation<3> class, only the tetrahedron gluings will be included in the SnapPea data file. All other SnapPea-specific information (such as peripheral curves) will be marked as unknown, since Regina does not track such information itself, and of course Regina-specific information (such as the Turaev-Viro invariants) will not be included in the SnapPea file either.
  • The subclass SnapPeaTriangulation implements its own version of this function, which writes all additional SnapPea-specific information to the file (in fact it uses the SnapPea kernel itself to produce the file contents). However, to access that function you must explicitly call SnapPeaTriangulation::saveSnapPea() (since Triangulation<3> is not a polymorphic class, and in particular this function is not virtual).

SnapPea cannot represent triangulations that are empty, invalid, or contain boundary triangles. If any of these conditions is true then the file will not be written and this routine will return false.

Internationalisation
This routine makes no assumptions about the character encoding used in the given file name, and simply passes it through unchanged to low-level C/C++ file I/O routines. The contents of the file will be written using UTF-8.
Parameters
filenamethe name of the SnapPea file to which to write.
Returns
true if and only if the file was successfully written.

◆ setGroupPresentation()

void regina::detail::TriangulationBase< dim >::setGroupPresentation ( GroupPresentation pres)
inlineinherited

Allows the specific presentation of the fundamental group to be changed by some other (external) means.

Specifically, this routine assumes that you have changed (and presumably simplified) the presentation of the fundamental group using some external tool (such as GAP or Magma), and it replaces the current presentation with the new presentation pres that is passed.

Regina does not verify that the new presentation is isomorphic to the old, since this is an extremely hard problem.

If the fundamental group has not yet been calculated for this triangulation, then this routine will cache pres as the fundamental group, under the assumption that you have worked out the group through some other clever means without ever having needed to call group() at all.

Note that this routine will not fire a packet change event.

Precondition
The given presentation pres is indeed a presentation of the fundamental group of this triangulation, as described by group().
Parameters
presa new presentation of the fundamental group of this triangulation.

◆ shellBoundary() [1/2]

bool regina::detail::TriangulationBase< dim >::shellBoundary ( Simplex< dim > * s)
inlineinherited

If possible, performs a boundary shelling move upon the given top-dimensional simplex of this triangulation.

This involves popping off a top-dimensional simplex with one or more facets on the boundary.

This move is only available in standard dimensions, since Regina's notion of "valid faces" is weaker in higher dimensions (due to the need to solve undecidable problems). See Face::isValid() for further discussion.

This triangulation will be changed directly.

This move will only be performed if it will not change the topology of the manifold (as outlined below), and it will not violate any simplex and/or facet locks. See Simplex<dim>::lock() and Simplex<dim>::lockFacet() for further details on locks.

In order to not change the topology, we require the conditions below. These are conditions are stricter than necessary, but the resulting "lost opportunities" only affect invalid triangulations.

In this list of conditions, we let s denote the given top-dimensional simplex, and we let f denote the face of s opposite the intersection of all its boundary facets. For example, for a 4-manifold triangulation where s has exactly two boundary facets meeting in a common boundary triangle, f would denote the edge of s opposite this common triangle. Put differently: f is the (unique) smallest face of s that might not be entirely contained in the triangulation boundary. Note that the dimension of f will be one less than the number of boundary facets of s.

Having said all of this, our conditions are:

  • all faces of all dimensions of the simplex s, except possibly its vertices, are valid;
  • at least one but not all of the facets of s lie in the boundary of the triangulation;
  • the face f (defined above) is valid (even if it is a vertex), and does not lie entirely in the boundary of the triangulation;
  • for each facial dimension k, no two k-faces of s that both contain f are identified (testing this for k = dim(f)+1 is enough to ensure it holds for all k).

If this triangulation is currently oriented, then this operation will (trivially) preserve the orientation.

Note that after performing this move, all skeletal objects (faces, components, etc.) will be reconstructed, which means any pointers to old skeletal objects can no longer be used.

Precondition
The dimension dim is one of Regina's standard dimensions.
The given simplex is a simplex of this triangulation.
Parameters
sthe top-dimensional simplex upon which to perform the move.
Returns
true if and only if the requested move was able to be performed.

◆ shellBoundary() [2/2]

bool regina::detail::TriangulationBase< dim >::shellBoundary ( Simplex< dim > * s,
bool ignored,
bool perform = true )
inlineinherited

Deprecated routine that tests for and optionally performs a boundary shelling move on the given top-dimensional simplex.

For more detail on boundary shelling moves and when they can be performed, see the variant of shellBoundary() without the extra boolean arguments.

This routine will always check whether the requested move is legal and will not violate any simplex and/or facet locks (see Simplex<dim>::lock() and Simplex<dim>::lockFacet() for further details on locks). If the move is allowed, and if the argument perform is true, this routine will also perform the move.

This move is only available in standard dimensions, since Regina's notion of "valid faces" is weaker in higher dimensions (due to the need to solve undecidable problems). See Face::isValid() for further discussion.

Deprecated
If you just wish to test whether such a move is possible, call hasShellBoundary(). If you wish to both check and perform the move, call shellBoundary() without the two extra boolean arguments.
Precondition
The dimension dim is one of Regina's standard dimensions.
The given simplex is a simplex of this triangulation.
Parameters
sthe top-dimensional simplex upon which to perform the move.
ignoredan argument that is ignored. In earlier versions of Regina this argument controlled whether we check if the move can be performed; however, now this check is done always.
performtrue if we should actually perform the move, assuming the move is allowed.
Returns
true if and only if the requested move could be performed.

◆ sig()

Encoding::Signature regina::detail::TriangulationBase< dim >::sig ( ) const
inlineinherited

Alias for isoSig(), which constructs the isomorphism signature of the given type for this triangulation.

This alias sig() is provided to assist with generic code that can work with both triangulations and links.

See isoSig() for further details.

Python
This alias is only available for the default signature type and encoding (i.e., the default C++ template arguments). If you wish to use a different signature type and/or encoding, you can instead use the variants provided with isoSig(); that is, you can call a function of the form isoSig_Type. See the isoSig() documentation for further details.
Returns
the isomorphism signature of this triangulation.

◆ simplex() [1/2]

Simplex< dim > * regina::detail::TriangulationBase< dim >::simplex ( size_t index)
inlineinherited

Returns the top-dimensional simplex at the given index in the triangulation.

Note that indexing may change when a simplex is added to or removed from the triangulation.

Parameters
indexspecifies which simplex to return; this value should be between 0 and size()-1 inclusive.
Returns
the indexth top-dimensional simplex.

◆ simplex() [2/2]

const Simplex< dim > * regina::detail::TriangulationBase< dim >::simplex ( size_t index) const
inlineinherited

Returns the top-dimensional simplex at the given index in the triangulation.

Note that indexing may change when a simplex is added to or removed from the triangulation.

Parameters
indexspecifies which simplex to return; this value should be between 0 and size()-1 inclusive.
Returns
the indexth top-dimensional simplex.

◆ simplices()

auto regina::detail::TriangulationBase< dim >::simplices ( ) const
inlineinherited

Returns an object that allows iteration through and random access to all top-dimensional simplices in this triangulation.

The object that is returned is lightweight, and can be happily copied by value. The C++ type of the object is subject to change, so C++ users should use auto (just like this declaration does).

The returned object is guaranteed to be an instance of ListView, which means it offers basic container-like functions and supports range-based for loops. Note that the elements of the list will be pointers, so your code might look like:

for (Simplex<dim>* s : tri.simplices()) { ... }
Represents a top-dimensional simplex in a dim-manifold triangulation.
Definition simplex.h:98
auto simplices() const
Definition triangulation.h:4631

The object that is returned will remain up-to-date and valid for as long as the triangulation exists: even as simplices are added and/or removed, it will always reflect the simplices that are currently in the triangulation. Nevertheless, it is recommended to treat this object as temporary only, and to call simplices() again each time you need it.

Returns
access to the list of all top-dimensional simplices.

◆ simplifiedFundamentalGroup()

void regina::detail::TriangulationBase< dim >::simplifiedFundamentalGroup ( GroupPresentation pres)
inlineinherited

Deprecated alias for setGroupPresentation(), which allows the specific presentation of the fundamental group to be changed by some other (external) means.

Deprecated
This routine has been renamed to setGroupPresentation().
Precondition
The given presentation pres is indeed a presentation of the fundamental group of this triangulation, as described by group().
Parameters
presa new presentation of the fundamental group of this triangulation.

◆ simplify()

bool regina::Triangulation< 3 >::simplify ( )

Attempts to simplify this triangulation as intelligently as possible using fast and greedy heuristics.

This routine will attempt to reduce the number of tetrahedra, the number of vertices and the number of boundary triangles (with the number of tetrahedra as its priority).

Currently this routine uses simplifyToLocalMinimum() and minimiseVertices() in combination with random 4-4 moves, book opening moves and book closing moves.

Although simplify() works very well most of the time, it can occasionally get stuck; in such cases you may wish to try the more powerful but (much) slower simplifyExhaustive() instead.

If this triangulation is currently oriented, then this operation will preserve the orientation.

If any tetrahedra and/or triangles are locked, these locks will be respected: that is, the simplification operation will avoid any moves that would violate these locks (and in particular, no LockViolation exceptions should be thrown). Of course, however, having locks may make the simplification less effective in reducing the number of tetrahedra.

Warning
Running this routine multiple times upon the same triangulation may return different results, since the implementation makes random decisions. More broadly, the implementation of this routine (and therefore its results) may change between different releases of Regina.
Note
For long-term users of Regina: this is the routine that was for a long time called intelligentSimplify(). It was renamed to simplify() in Regina 7.4.
Todo
Optimise: Include random 2-3 moves to get out of wells.
Returns
true if and only if the triangulation was successfully simplified. Otherwise this triangulation will not be changed.

◆ simplifyExhaustive()

bool regina::Triangulation< 3 >::simplifyExhaustive ( int height = 1,
int threads = 1,
ProgressTrackerOpen * tracker = nullptr )

Attempts to simplify this triangulation using a slow but exhaustive search through the Pachner graph.

This routine is more powerful but much slower than simplify().

Specifically, this routine will iterate through all triangulations that can be reached from this triangulation via 2-3 and 3-2 Pachner moves, without ever exceeding height additional tetrahedra beyond the original number, and without violating any simplex and/or facet locks.

If at any stage it finds a triangulation with fewer tetrahedra than the original, then this routine will call simplify() to shrink the triangulation further if possible and will then return true. If it cannot find a triangulation with fewer tetrahedra then it will leave this triangulation unchanged and return false.

This routine can be very slow and very memory-intensive: the number of triangulations it visits may be superexponential in the number of tetrahedra, and it records every triangulation that it visits (so as to avoid revisiting the same triangulation again). It is highly recommended that you begin with height = 1, and if this fails then try increasing height one at a time until either you find a simplification or the routine becomes too expensive to run.

If height is negative, then there will be no bound on the number of additional tetrahedra. This means that the routine will not terminate until a simpler triangulation is found (unless there are so many locks that the number of reachable triangulations is finite). This means that, if no simpler triangulation exists, the only way to terminate this function is to cancel the operation via a progress tracker (read on for details).

If this triangulation is currently oriented, then this operation will not preserve the orientation: indeed, the resulting triangulation might not be oriented at all. This is a consequence of the way in which this operation uses isomorphism signatures to represent nodes in the Pachner graph. If you need a simplification routine that preserves orientation, you should use simplify() instead.

If any tetrahedra and/or triangles are locked, these locks will be respected: that is, the retriangulation will avoid any moves that would violate these locks (and in particular, no LockViolation exceptions should be thrown). Of course, however, having locks may reduce the number of distinct triangulations that can be reached.

If you want a fast simplification routine, you should call simplify() instead. The benefit of simplifyExhaustive() is that, for very stubborn triangulations where simplify() finds itself stuck at a local minimum, simplifyExhaustive() is able to "climb out" of such wells.

Since Regina 7.0, this routine will not return until either the triangulation is simplified or the exhaustive search is complete, regardless of whether a progress tracker was passed. If you need the old behaviour (where passing a progress tracker caused the exhaustive search to start in the background), simply call this routine in a new detached thread.

To assist with performance, this routine can run in parallel (multithreaded) mode; simply pass the number of parallel threads in the argument threads. Even in multithreaded mode, this routine will not return until processing has finished (i.e., either the triangulation was simplified or the search was exhausted), and any change to this triangulation will happen in the calling thread.

If this routine is unable to simplify the triangulation, then the triangulation will not be changed.

Precondition
This triangulation is connected.
Exceptions
FailedPreconditionThis triangulation has more than one connected component. If a progress tracker was passed, it will be marked as finished before the exception is thrown.
Python
The global interpreter lock will be released while this function runs, so you can use it with Python-based multithreading.
Parameters
heightthe maximum number of additional tetrahedra to allow beyond the number of tetrahedra originally present in the triangulation, or a negative number if this should not be bounded.
threadsthe number of threads to use. If this is 1 or smaller then the routine will run single-threaded.
trackera progress tracker through which progress will be reported, or null if no progress reporting is required.
Returns
true if and only if the triangulation was successfully simplified to fewer tetrahedra.

◆ simplifyToLocalMinimum()

bool regina::Triangulation< 3 >::simplifyToLocalMinimum ( bool perform = true)

Uses all known simplification moves to reduce the triangulation monotonically to some local minimum number of tetrahedra.

End users will probably not want to call this routine. You should call simplify() if you want a fast (and usually effective) means of simplifying a triangulation, or you should call simplifyExhaustive() if you are still stuck and you want to try a slower but more powerful method instead.

The moves used by this routine include 3-2, 2-0 (edge and vertex), 2-1 and boundary shelling moves.

Moves that do not reduce the number of tetrahedra (such as 4-4 moves or book opening moves) are not used in this routine. Such moves do however feature in simplify().

If this triangulation is currently oriented, then this operation will preserve the orientation.

If any tetrahedra and/or triangles are locked, these locks will be respected: that is, the simplification operation will avoid any moves that would violate these locks (and in particular, no LockViolation exceptions should be thrown). Of course, however, having locks may make the simplification less effective in reducing the number of tetrahedra.

Warning
The implementation of this routine (and therefore its results) may change between different releases of Regina.
Parameters
performtrue if we are to perform the simplifications, or false if we are only to investigate whether simplifications are possible (defaults to true).
Returns
if perform is true, this routine returns true if and only if the triangulation was changed to reduce the number of tetrahedra; if perform is false, this routine returns true if and only if it determines that it is capable of performing such a change.

◆ size()

size_t regina::detail::TriangulationBase< dim >::size ( ) const
inlineinherited

Returns the number of top-dimensional simplices in the triangulation.

Returns
The number of top-dimensional simplices.

◆ snapPea() [1/2]

std::string regina::Triangulation< 3 >::snapPea ( ) const

Returns a string containing the full contents of a SnapPea data file that describes this triangulation.

In particular, this string can be used in a Python session to pass the triangulation directly to SnapPy (without writing to the filesystem).

Regarding what gets stored in the SnapPea data file:

  • Since this function is defined by Regina's own Triangulation<3> class, only the tetrahedron gluings will be included in the SnapPea data file. All other SnapPea-specific information (such as peripheral curves) will be marked as unknown, since Regina does not track such information itself, and of course Regina-specific information (such as the Turaev-Viro invariants) will not be included in the SnapPea file either.
  • The subclass SnapPeaTriangulation implements its own version of this function, which writes all additional SnapPea-specific information to the file (in fact it uses the SnapPea kernel itself to produce the file contents). However, to access that function you must explicitly call SnapPeaTriangulation::snapPea() (since Triangulation<3> is not a polymorphic class, and in particular this function is not virtual).

If you wish to export a triangulation to a SnapPea file, you should call saveSnapPea() instead (which has better performance, and does not require you to construct an enormous intermediate string).

SnapPea cannot represent triangulations that are empty, invalid, or contain boundary triangles. If any of these conditions is true then this routine will throw an exception.

Exceptions
NotImplementedThis triangulation is either empty, invalid, or has boundary triangles.
Returns
a string containing the contents of the corresponding SnapPea data file.

◆ snapPea() [2/2]

void regina::Triangulation< 3 >::snapPea ( std::ostream & out) const

Writes the full contents of a SnapPea data file describing this triangulation to the given output stream.

Regarding what gets stored in the SnapPea data file:

  • Since this function is defined by Regina's own Triangulation<3> class, only the tetrahedron gluings will be included in the SnapPea data file. All other SnapPea-specific information (such as peripheral curves) will be marked as unknown, since Regina does not track such information itself, and of course Regina-specific information (such as the Turaev-Viro invariants) will not be included in the SnapPea file either.
  • The subclass SnapPeaTriangulation implements its own version of this function, which writes all additional SnapPea-specific information to the file (in fact it uses the SnapPea kernel itself to produce the file contents). However, to access that function you must explicitly call SnapPeaTriangulation::snapPea() (since Triangulation<3> is not a polymorphic class, and in particular this function is not virtual).

If you wish to extract the SnapPea data file as a string, you should call the zero-argument routine snapPea() instead. If you wish to write to a real SnapPea data file on the filesystem, you should call saveSnapPea() (which is also available in Python).

SnapPea cannot represent triangulations that are empty, invalid, or contain boundary triangles. If any of these conditions is true then this routine will throw an exception.

Exceptions
NotImplementedThis triangulation is either empty, invalid, or has boundary triangles.
Python
Not present. Instead call snapPea() with no arguments, which returns this data as a string.
Parameters
outthe output stream to which the SnapPea data file will be written.

◆ source()

std::string regina::detail::TriangulationBase< dim >::source ( Language language = Language::Current) const
inherited

Returns C++ or Python source code that can be used to reconstruct this triangulation.

This code will call Triangulation<dim>::fromGluings(), passing a hard-coded C++ initialiser list or Python list (depending on the requested language).

The main purpose of this routine is to generate this hard-coded list, which can be tedious and error-prone to write by hand.

Note that the number of lines of code produced grows linearly with the number of simplices. If this triangulation is very large, the returned string will be very large as well.

Parameters
languagethe language in which the source code should be written.
Returns
the source code that was generated.

◆ str()

std::string regina::Output< Triangulation< dim >, false >::str ( ) const
inherited

Returns a short text representation of this object.

This text should be human-readable, should use plain ASCII characters where possible, and should not contain any newlines.

Within these limits, this short text ouptut should be as information-rich as possible, since in most cases this forms the basis for the Python __str__() and __repr__() functions.

Python
The Python "stringification" function __str__() will use precisely this function, and for most classes the Python __repr__() function will incorporate this into its output.
Returns
a short text representation of this object.

◆ strictAngleStructure()

const AngleStructure & regina::Triangulation< 3 >::strictAngleStructure ( ) const
inline

Returns a strict angle structure on this triangulation, if one exists.

Recall that a strict angle structure is one in which every angle is strictly between 0 and π. If a strict angle structure does exist, then this routine is guaranteed to return one.

This routine is designed for scenarios where you already know that a strict angle structure exists. This means:

  • If no strict angle structure exists, this routine will throw an exception, which will incur a significant overhead.
  • If you do not know in advance whether a strict angle structure exists, you should call hasStrictAngleStructure() first. If the answer is no, this will avoid the overhead of throwing and catching exceptions. If the answer is yes, this will have the side-effect of caching the strict angle structure, which means your subsequent call to strictAngleStructure() will be essentially instantaneous.

The underlying algorithm runs a single linear program (it does not enumerate all vertex angle structures). This means that it is likely to be fast even for large triangulations.

The result of this routine is cached internally: as long as the triangulation does not change, multiple calls to strictAngleStructure() will return identical angle structures, and every call after the first be essentially instantaneous.

If the triangulation does change, however, then the cached angle structure will be deleted, and any reference that was returned before will become invalid.

As of Regina 7.4, this routine has changed its behaviour for the empty triangulation: it now returns the empty angle structure, which is (strictly speaking) both strict and taut.

Exceptions
NoSolutionNo strict angle structure exists on this triangulation.
Returns
a strict angle structure on this triangulation, if one exists.

◆ subdivide()

void regina::detail::TriangulationBase< dim >::subdivide ( )
inherited

Does a barycentric subdivision of the triangulation.

This is done in-place, i.e., the triangulation will be modified directly.

Each top-dimensional simplex s is divided into (dim + 1) factorial sub-simplices by placing an extra vertex at the centroid of every face of every dimension. Each of these sub-simplices t is described by a permutation p of (0, ..., dim). The vertices of such a sub-simplex t are:

  • vertex p[0] of s;
  • the centre of edge (p[0], p[1]) of s;
  • the centroid of triangle (p[0], p[1], p[2]) of s;
  • ...
  • the centroid of face (p[0], p[1], p[2], p[dim]) of s, which is the entire simplex s itself.

The sub-simplices have their vertices numbered in a way that mirrors the original simplex s:

  • vertex p[0] of s will be labelled p[0] in t;
  • the centre of edge (p[0], p[1]) of s will be labelled p[1] in t;
  • the centroid of triangle (p[0], p[1], p[2]) of s will be labelled p[2] in t;
  • ...
  • the centroid of s itself will be labelled p[dim] in t.

In particular, if this triangulation is currently oriented, then this barycentric subdivision will preserve the orientation.

If simplex s has index i in the original triangulation, then its sub-simplex corresponding to permutation p will have index ((dim + 1)! * i + p.orderedSnIndex()) in the resulting triangulation. In other words: sub-simplices are ordered first according to the original simplex that contains them, and then according to the lexicographical ordering of the corresponding permutations p.

Precondition
dim is one of Regina's standard dimensions. This precondition is a safety net, since in higher dimensions the triangulation would explode too quickly in size (and for the highest dimensions, possibly beyond the limits of size_t).
Warning
In dimensions 3 and 4, both the labelling and ordering of sub-simplices in the subdivided triangulation has changed as of Regina 5.1. (Earlier versions of Regina made no guarantee about the labelling and ordering; these guarantees are also new to Regina 5.1).
Exceptions
LockViolationThis triangulation contains at least one locked top-dimensional simplex and/or facet. This exception will be thrown before any changes are made. See Simplex<dim>::lock() and Simplex<dim>::lockFacet() for further details on how such locks work and what their implications are.
Todo
Lock the topological properties of the underlying manifold, to avoid recomputing them after the subdivision. However, only do this for valid triangulations (since we can have scenarios where invalid triangulations becoming valid and ideal after subdivision, which may change properties such as Triangulation<4>::knownSimpleLinks).

◆ summands()

std::vector< Triangulation< 3 > > regina::Triangulation< 3 >::summands ( ) const

Computes the connected sum decomposition of this triangulation.

The prime summands will be returned as a vector of triangulations; this triangulation will not be modified.

As far as possible, the summands will be represented using 0-efficient triangulations (i.e., triangulations that contain no non-vertex-linking normal spheres). Specifically, for every summand, either:

  • the triangulation of the summand that is produced will be 0-efficient; or
  • the summand is one of RP3, the product S2xS1, or the twisted product S2x~S1. In each of these cases there is no possible 0-efficient triangulation of the summand, and so the triangulation that is produced will just be minimal (i.e., two tetrahedra).

For non-orientable triangulations, this routine is only guaranteed to succeed if the original manifold contains no embedded two-sided projective planes. If the manifold does contain embedded two-sided projective planes, then this routine might still succeed but it might fail; however, such a failure will always be detected, and in such a case this routine will throw an exception (as detailed below).

Note that this routine is currently only available for closed triangulations; see the list of preconditions for full details. If this triangulation is a 3-sphere then this routine will return an empty list.

This function is new to Regina 7.0, and it has some important changes of behaviour from the old connectedSumDecomposition() from Regina 6.0.1 and earlier:

  • This function does not insert the resulting components into the packet tree.
  • If this routine fails because of an embedded two-sided projective plane, then it throws an exception instead of returning -1.
  • This function does not assign labels to the new summands.

The underlying algorithm appears in "A new approach to crushing 3-manifold triangulations", Discrete and Computational Geometry 52:1 (2014), pp. 116-139. This algorithm is based on the Jaco-Rubinstein 0-efficiency algorithm, and works in both orientable and non-orientable settings.

If this triangulation is oriented, be aware that the summands might not inherit this orientation. In particular, given the way that the crushing algorithm works, it is not clear how to maintain the orientations of any L(3,1) summands.

If any tetrahedra and/or triangles in this triangulation are locked, this will not prevent summands() from doing its work (since the original triangulation will not be changed). The triangulations that are returned (i.e., the prime summands) will have no simplex and/or facet locks at all.

Warning
Users are strongly advised to check for exceptions if embedded two-sided projective planes are a possibility, since in such a case this routine might fail (as explained above). Note however that this routine might still succeed, and so success is not a proof that no embedded two-sided projective planes exist.
The algorithms used in this routine rely on normal surface theory and so can be very slow for larger triangulations. For 3-sphere testing, see the routine isSphere() which uses faster methods where possible.
Precondition
This triangulation is valid, closed and connected.
Exceptions
UnsolvedCaseThe original manifold is non-orientable and contains one or more embedded two-sided projective planes, and this routine was not able to recover from this situation.
Returns
a list of triangulations of prime summands.

◆ swap() [1/2]

void regina::Snapshottable< Triangulation< dim > >::swap ( Snapshottable< Triangulation< dim > > & other)
inlineprotectednoexceptinherited

Swap operation.

This should only be called when the entire type T contents of this object and other are being swapped. If one object has a current snapshot, then the other object will move in as the new image for that same snapshot. This avoids a deep copies of this object and/or other, even though both objects are changing.

In particular, if the swap function for T calls this base class function (as it should), then there is no need to call takeSnapshot() from either this object or src.

Parameters
otherthe snapshot image being swapped with this.

◆ swap() [2/2]

void regina::Triangulation< 3 >::swap ( Triangulation< 3 > & other)

Swaps the contents of this and the given triangulation.

All tetrahedra that belong to this triangulation will be moved to other, and all tetrahedra that belong to other will be moved to this triangulation. Likewise, all skeletal objects (such as lower-dimensional faces, components, and boundary components) and all cached properties (such as homology and fundamental group) will be swapped.

In particular, any pointers or references to Tetrahedron<3> and/or Face<3, subdim> objects will remain valid.

This routine will behave correctly if other is in fact this triangulation.

Note
This swap function is not marked noexcept, since it fires change events on both triangulations which may in turn call arbitrary code via any registered packet listeners.
Parameters
otherthe triangulation whose contents should be swapped with this.

◆ swapBaseData()

void regina::detail::TriangulationBase< dim >::swapBaseData ( TriangulationBase< dim > & other)
protectedinherited

Swaps all data that is managed by this base class, including simplices, skeletal data, cached properties and the snapshotting data, with the given triangulation.

Note that TriangulationBase never calls this routine itself. Typically swapBaseData() is only ever called by Triangulation<dim>::swap().

Parameters
otherthe triangulation whose data should be swapped with this.

◆ takeSnapshot()

void regina::Snapshottable< Triangulation< dim > >::takeSnapshot ( )
inlineprotectedinherited

Must be called before modification and/or destruction of the type T contents.

See the Snapshot class notes for a full explanation of how this requirement works.

There are a few exceptions where takeSnapshot() does not need to be called: these are where type T move, copy and/or swap operations call the base class operations (as they should). See the Snapshottable move, copy and swap functions for details.

If this object has a current snapshot, then this function will trigger a deep copy with the snapshot.

After this function returns, this object is guaranteed to be completely unenrolled from the snapshotting machinery.

◆ tetrahedra()

auto regina::detail::TriangulationBase< dim >::tetrahedra ( ) const
inlineinherited

A dimension-specific alias for faces<3>(), or an alias for simplices() in dimension dim = 3.

This alias is available for dimensions dim ≥ 3.

See faces() for further information.

◆ tetrahedron() [1/2]

auto regina::detail::TriangulationBase< dim >::tetrahedron ( size_t index)
inlineinherited

A dimension-specific alias for face<3>(), or an alias for simplex() in dimension dim = 3.

This alias is available for dimensions dim ≥ 3. It returns a non-const tetrahedron pointer.

See face() for further information.

◆ tetrahedron() [2/2]

auto regina::detail::TriangulationBase< dim >::tetrahedron ( size_t index) const
inlineinherited

A dimension-specific alias for face<3>(), or an alias for simplex() in dimension dim = 3.

This alias is available for dimensions dim ≥ 3. It returns a const tetrahedron pointer in dimension dim = 3, and a non-const tetrahedron pointer in all higher dimensions.

See face() for further information.

◆ tightDecode()

Triangulation< dim > regina::detail::TriangulationBase< dim >::tightDecode ( std::istream & input)
staticinherited

Reconstructs a triangulation from its given tight encoding.

See the page on tight encodings for details.

The tight encoding will be read from the given input stream. If the input stream contains leading whitespace then it will be treated as an invalid encoding (i.e., this routine will throw an exception). The input stream may contain further data: if this routine is successful then the input stream will be left positioned immediately after the encoding, without skipping any trailing whitespace.

Exceptions
InvalidInputThe given input stream does not begin with a tight encoding of a dim-dimensional triangulation.
Python
Not present. Use tightDecoding() instead, which takes a string as its argument.
Parameters
inputan input stream that begins with the tight encoding for a dim-dimensional triangulation.
Returns
the triangulation represented by the given tight encoding.

◆ tightDecoding()

static Triangulation< dim > regina::TightEncodable< Triangulation< dim > >::tightDecoding ( const std::string & enc)
inlinestaticinherited

Reconstructs an object of type T from its given tight encoding.

See the page on tight encodings for details.

The tight encoding should be given as a string. If this string contains leading whitespace or any trailing characters at all (including trailing whitespace), then it will be treated as an invalid encoding (i.e., this routine will throw an exception).

Exceptions
InvalidArgumentThe given string is not a tight encoding of an object of type T.
Parameters
encthe tight encoding for an object of type T.
Returns
the object represented by the given tight encoding.

◆ tightEncode()

void regina::detail::TriangulationBase< dim >::tightEncode ( std::ostream & out) const
inherited

Writes the tight encoding of this triangulation to the given output stream.

See the page on tight encodings for details.

Python
Not present. Use tightEncoding() instead, which returns a string.
Parameters
outthe output stream to which the encoded string will be written.

◆ tightEncoding()

std::string regina::TightEncodable< Triangulation< dim > >::tightEncoding ( ) const
inlineinherited

Returns the tight encoding of this object.

See the page on tight encodings for details.

Exceptions
FailedPreconditionThis may be thrown for some classes T if the object is in an invalid state. If this is possible, then a more detailed explanation of "invalid" can be found in the class documentation for T, under the member function T::tightEncode(). See FacetPairing::tightEncode() for an example of this.
Returns
the resulting encoded string.

◆ topologyLocked()

bool regina::TopologyLockable::topologyLocked ( ) const
inlineprotectedinherited

Returns whether or not there are any topology locks currently held on this object.

Strictly speaking, this routine could return a false negative: the number of locks is stored as an 8-bit integer and so in reality this tests whether the number of locks is a multiple of 256. False negatives are mathematically harmless, since the worst that will happen is that topological properties will be cleared when they could have been preserved, and so unnecessary extra computation may be required to compute them again.

This routine will never return a false positive.

Returns
false if there are no topology locks currently held on this object, or if a false negative occurs (as described above); or true to indicate that there are currently topology locks held on this object.

◆ translate() [1/2]

Face< dim, subdim > * regina::detail::TriangulationBase< dim >::translate ( const Face< dim, subdim > * other) const
inlineinherited

Translates a face of some other triangulation into the corresponding face of this triangulation, using simplex numbers for the translation.

Typically this routine would be used when the given face comes from a triangulation that is combinatorially identical to this, and you wish to obtain the corresponding face of this triangulation.

Specifically:

  • For faces of dimension k < dim, if other refers to face i of top-dimensional simplex number k of some other triangulation, then this routine will return face i of top-dimensional simplex number k of this triangulation. Note that this routine does not use the face indices within each triangulation (which is outside the user's control), but rather the simplex numbering (which the user has full control over).
  • For top-dimensional simplices (i.e., faces of dimension k = dim), this routine will simply translate top-dimensional simplex number k of some other triangulation into top-dimensional simplex number k of this triangulation.

This routine behaves correctly even if other is a null pointer.

Precondition
This triangulation contains at least as many top-dimensional simplices as the triangulation containing other (though, as noted above, in typical scenarios both triangulations would actually be combinatorially identical).
Template Parameters
subdimthe face dimension; this must be between 0 and dim inclusive.
Parameters
otherthe face to translate.
Returns
the corresponding face of this triangulation.

◆ translate() [2/2]

FaceEmbedding< dim, subdim > regina::detail::TriangulationBase< dim >::translate ( const FaceEmbedding< dim, subdim > & other) const
inlineinherited

Translates a face embedding from some other triangulation into the corresponding face embedding with respect to this triangulation, using simplex numbers for the translation.

Typically this routine would be used when the given embedding comes from a triangulation that is combinatorially identical to this, and you wish to obtain the corresponding face embedding within this triangulation.

Specifically: if the embedding other refers to face i of top-dimensional simplex number k of some other triangulation, then the embedding that is returned will refer to face i of top-dimensional simplex number k of this triangulation.

Precondition
This triangulation contains at least as many top-dimensional simplices as the triangulation containing other (though, as noted above, in typical scenarios both triangulations would actually be combinatorially identical).
Template Parameters
subdimthe face dimension; this must be between 0 and dim-1 inclusive.
Parameters
otherthe face embedding to translate.
Returns
the corresponding face embedding in this triangulation.

◆ triangle() [1/2]

auto regina::detail::TriangulationBase< dim >::triangle ( size_t index)
inlineinherited

A dimension-specific alias for face<2>(), or an alias for simplex() in dimension dim = 2.

This alias is available for all dimensions dim. It returns a non-const triangle pointer.

See face() for further information.

◆ triangle() [2/2]

auto regina::detail::TriangulationBase< dim >::triangle ( size_t index) const
inlineinherited

A dimension-specific alias for face<2>(), or an alias for simplex() in dimension dim = 2.

This alias is available for all dimensions dim. It returns a const triangle pointer in dimension dim = 2, and a non-const triangle pointer in all higher dimensions.

See face() for further information.

◆ triangles()

auto regina::detail::TriangulationBase< dim >::triangles ( ) const
inlineinherited

A dimension-specific alias for faces<2>(), or an alias for simplices() in dimension dim = 2.

This alias is available for all dimensions.

See faces() for further information.

◆ triangulateComponents()

std::vector< Triangulation< dim > > regina::detail::TriangulationBase< dim >::triangulateComponents ( ) const
inherited

Returns the individual connected components of this triangulation.

This triangulation will not be modified.

This function is new to Regina 7.0, and it has two important changes of behaviour from the old splitIntoComponents() from Regina 6.0.1 and earlier:

  • This function does not insert the resulting components into the packet tree.
  • This function does not assign labels to the new components.

If this triangulation has locks on any top-dimensional simplices and/or their facets, these locks will also be copied over to the newly-triangulated components.

Returns
a list of individual component triangulations.

◆ truncate()

void regina::Triangulation< 3 >::truncate ( Vertex< 3 > * vertex,
bool lockBoundary = false )
inline

Truncates the given vertex.

If the vertex is internal (its link is a sphere), then this will create a new real 2-sphere boundary component. If the vertex is ideal, then this will effectively convert the ideal boundary component into a real boundary component made from triangles.

If you wish to truncate all ideal (and/or invalid) vertices of the triangulation, you can call truncateIdeal() instead.

Regarding locks:

  • This routine induces a subdivision of the entire triangulation. Therefore any simplex and/or facet locks that exist before this routine is run will prevent the operation from taking place, instead causing a LockViolation to be thrown.
  • If the optional argument lockBoundary is passed as true, then this routine will lock all boundary facets along the surface where the truncation took place (i.e., the link of the original vertex). This may be useful if you wish to distinguish between "old" boundary (real boundary that existed before the truncation) and "new" boundary (real boundary that was created as a result of the truncation).

A note: this operation does not preserve orientedness. That is, regardless of whether this triangulation was oriented before calling this function, it will not be oriented after. This is due to the specific choice of tetrahedron vertex labelling in the subdivision, and this behaviour may change in a future version of Regina.

Exceptions
LockViolationThis triangulation contains at least one locked top-dimensional simplex and/or facet. This exception will be thrown before any changes are made. See Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on how such locks work and what their implications are.
Parameters
vertexthe vertex to truncate.
lockBoundarytrue if and only if this routine should lock all boundary facets along the truncation surface.

◆ truncateIdeal()

bool regina::Triangulation< 3 >::truncateIdeal ( )
inline

Truncates all ideal or invalid vertices, converting these into real boundary components made from unglued faces of tetrahedra.

This operation is equivalent to calling truncate() on every ideal or invalid vertex. It also serves as a loose converse to makeIdeal().

If this triangulation has any invalid edges, then these will remain invalid after this operation (in contrast to barycentric subdivision, which converts invalid edges into projective plane cusps). As of Regina 7.4, the presence of invalid edges will no longer cause the triangulation to be subdivided if there are no vertices to truncate.

A note: this operation does not preserve orientedness. That is, regardless of whether this triangulation was oriented before calling this function, it will not be oriented after. This is due to the specific choice of tetrahedron vertex labelling in the subdivision, and this behaviour may change in a future version of Regina.

This routine was called idealToFinite() in older versions of Regina, since its main job is to convert an ideal triangulation into a finite triangulation.

Warning
Currently, this routine subdivides all tetrahedra as if all vertices (not just some) were ideal. This may lead to more tetrahedra than are necessary.
Exceptions
LockViolationThis triangulation contains at least one locked top-dimensional simplex and/or facet. This exception will be thrown before any changes are made. See Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on how such locks work and what their implications are.
Todo
Optimise (long-term): Have this routine only use as many tetrahedra as are necessary, leaving finite vertices alone.
Returns
true if and only if the triangulation was changed.

◆ turaevViro()

Cyclotomic regina::Triangulation< 3 >::turaevViro ( unsigned long r,
bool parity = true,
Algorithm alg = Algorithm::Default,
ProgressTracker * tracker = nullptr ) const

Computes the given Turaev-Viro state sum invariant of this 3-manifold using exact arithmetic.

The initial data for the Turaev-Viro invariant is as described in the paper of Turaev and Viro, "State sum invariants of 3-manifolds and quantum 6j-symbols", Topology, vol. 31, no. 4, 1992, pp 865-902. In particular, Section 7 of this paper describes the initial data as determined by an integer r ≥ 3, and a root of unity q₀ of degree 2r for which q₀² is a primitive root of unity of degree r. There are several cases to consider:

  • r may be even. In this case qâ‚€ must be a primitive (2r)th root of unity, and the invariant is computed as an element of the cyclotomic field of order 2r. There is no need to specify which root of unity is used, since switching between different roots of unity corresponds to an automorphism of the underlying cyclotomic field (i.e., it does not yield any new information). Therefore, if r is even, the additional argument parity is ignored.
  • r may be odd, and qâ‚€ may be a primitive (2r)th root of unity. This case corresponds to passing the argument parity as true. Here the invariant is again computed as an element of the cyclotomic field of order 2r. As before, there is no need to give further information as to which root of unity is used, since switching between roots of unity does not yield new information.
  • r may be odd, and qâ‚€ may be a primitive (r)th root of unity. This case corresponds to passing the argument parity as false. In this case the invariant is computed as an element of the cyclotomic field of order r. Again, there is no need to give further information as to which root of unity is used.

This routine works entirely within the relevant cyclotomic field, which yields exact results but adds a significant overhead to the running time. If you want a fast floating-point approximation, you can call turaevViroApprox() instead.

Unlike this routine, turaevViroApprox() requires a precise specification of which root of unity is used (since it returns a numerical real value). The numerical value obtained by calling turaevViroApprox(r, whichRoot) should be the same as turaevViro(r, parity).evaluate(whichRoot), where parity is true or false according to whether whichRoot is odd or even respectively. Of course in practice the numerical values might be very different, since turaevViroApprox() performs significantly more floating-point operations, and so is subject to a much larger potential numerical error.

If the requested Turaev-Viro invariant has already been computed, then the result will be cached and so this routine will be very fast (since it just returns the previously computed result). Otherwise the computation could be quite slow, particularly for larger triangulations and/or larger values of r.

Since Regina 7.0, this routine will not return until the Turaev-Viro computation is complete, regardless of whether a progress tracker was passed. If you need the old behaviour (where passing a progress tracker caused the computation to start in the background), simply call this routine in a new detached thread.

Precondition
This triangulation is valid, closed and non-empty.
Python
The global interpreter lock will be released while this function runs, so you can use it with Python-based multithreading.
Exceptions
FailedPreconditionThis triangulation is not valid, closed and non-empty.
InvalidArgumentThe argument r is less than 3.
Parameters
rthe integer r as described above; this must be at least 3.
paritydetermines for odd r whether qâ‚€ is a primitive 2rth or rth root of unity, as described above.
algthe algorithm with which to compute the invariant. If you are not sure, the default value (Algorithm::Default) is a safe choice. This should be treated as a hint only: if the algorithm you choose is not supported for the given parameters (r and parity), then Regina will use another algorithm instead.
trackera progress tracker through will progress will be reported, or null if no progress reporting is required.
Returns
the requested Turaev-Viro invariant, or an uninitialised field element if the calculation was cancelled via the given progress tracker.
See also
allCalculatedTuraevViro

◆ turaevViroApprox()

double regina::Triangulation< 3 >::turaevViroApprox ( unsigned long r,
unsigned long whichRoot = 1,
Algorithm alg = Algorithm::Default ) const

Computes the given Turaev-Viro state sum invariant of this 3-manifold using a fast but inexact floating-point approximation.

The initial data for the Turaev-Viro invariant is as described in the paper of Turaev and Viro, "State sum invariants of 3-manifolds and quantum 6j-symbols", Topology, vol. 31, no. 4, 1992, pp 865-902. In particular, Section 7 describes the initial data as determined by an integer r ≥ 3 and a root of unity q₀ of degree 2r for which q₀² is a primitive root of unity of degree r.

The argument whichRoot specifies which root of unity is used for q₀. Specifically, q₀ will be the root of unity e^(2πi * whichRoot / 2r). There are additional preconditions on whichRoot to ensure that q₀² is a primitive root of unity of degree r; see below for details.

This same invariant can be computed by calling turaevViro(r, parity).evaluate(whichRoot), where parity is true or false according to whether whichRoot is odd or even respectively. Calling turaevViroApprox() is significantly faster (since it avoids the overhead of working in cyclotomic fields), but may also lead to a much larger numerical error (since this routine might perform an exponential number of floating-point operations, whereas the alternative only uses floating-point for the final call to Cyclotomic::evaluate()).

These invariants, although computed in the complex field, should all be reals. Thus the return type is an ordinary double.

Precondition
This triangulation is valid, closed and non-empty.
The argument whichRoot is strictly between 0 and 2r, and has no common factors with r.
Exceptions
FailedPreconditionThis triangulation is not valid, closed and non-empty.
InvalidArgumentthe argument r is less than 3, or the argument whichRoot is not both coprime to r and between 0 and 2r.
Parameters
rthe integer r as described above; this must be at least 3.
whichRootspecifies which root of unity is used for qâ‚€, as described above.
algthe algorithm with which to compute the invariant. If you are not sure, the default value (Algorithm::Default) is a safe choice. This should be treated as a hint only: if the algorithm you choose is not supported for the given parameters (r and whichRoot), then Regina will use another algorithm instead.
Returns
the requested Turaev-Viro invariant.
See also
allCalculatedTuraevViro

◆ twoOneMove()

bool regina::Triangulation< 3 >::twoOneMove ( Edge< 3 > * e,
int edgeEnd,
bool ignored,
bool perform = true )
inline

Deprecated routine that tests for and optionally performs a 2-1 move at the given end of the given edge of this triangulation.

For more details on 2-1 moves and when they can be performed, see move21().

This routine will always check whether the requested move is legal and will not violate any simplex and/or facet locks (see Simplex<3>::lock() and Simplex<3>::lockFacet() for further details on locks). If the move is allowed, and if the argument perform is true, this routine will also perform the move.

Deprecated
If you just wish to test whether such a move is possible, call has21(). If you wish to both check and perform the move, call move21().
Precondition
The given edge is an edge of this triangulation.
Parameters
ethe edge about which to perform the move.
edgeEndindicates at which end of the edge e the move does not involve the adjacent tetrahedron; this should be 0 or 1. See move21() for details on exactly what this means.
ignoredan argument that is ignored. In earlier versions of Regina this argument controlled whether we check if the move can be performed; however, now this check is done always.
performtrue if we should actually perform the move, assuming the move is allowed.
Returns
true if and only if the requested move could be performed.

◆ twoZeroMove()

bool regina::detail::TriangulationBase< dim >::twoZeroMove ( Face< dim, k > * f,
bool ignored,
bool perform = true )
inlineinherited

Deprecated routine that tests for and optionally performs a 2-0 move about the given k-face of this triangulation.

For more detail on 2-0 moves and when they can be performed, see move20().

This routine will always check whether the requested move is legal and will not violate any simplex and/or facet locks (see Simplex<dim>::lock() and Simplex<dim>::lockFacet() for further details on locks). If the move is allowed, and if the argument perform is true, this routine will also perform the move.

Deprecated
If you just wish to test whether such a move is possible, call has20(). If you wish to both check and perform the move, call move20(), which does not take the two extra boolean arguments.
Precondition
The given k-face is a k-face of this triangulation.
Template Parameters
kthe dimension of the given face. This must be 0, 1 or 2, and must not exceed dim - 2.
Parameters
fthe k-face about which to perform the move.
ignoredan argument that is ignored. In earlier versions of Regina this argument controlled whether we check if the move can be performed; however, now this check is done always.
performtrue if we should actually perform the move, assuming the move is allowed.
Returns
true if and only if the requested move could be performed.

◆ unlockAll()

void regina::detail::TriangulationBase< dim >::unlockAll ( )
inherited

Unlocks all top-dimensional simplices and their facets.

In short, locking a top-dimensional simplex and/or some of its facets means that that the simplex and/or facets must not be changed. See Simplex<dim>::lock() and Simplex<dim>::lockFacet() for full details on how locks work and what their implications are.

After this is routine called, hasLocks() will return false.

◆ utf8()

std::string regina::Output< Triangulation< dim >, false >::utf8 ( ) const
inherited

Returns a short text representation of this object using unicode characters.

Like str(), this text should be human-readable, should not contain any newlines, and (within these constraints) should be as information-rich as is reasonable.

Unlike str(), this function may use unicode characters to make the output more pleasant to read. The string that is returned will be encoded in UTF-8.

Returns
a short text representation of this object.

◆ vertex()

Face< dim, 0 > * regina::detail::TriangulationBase< dim >::vertex ( size_t index) const
inlineinherited

A dimension-specific alias for face<0>().

This alias is available for all dimensions dim.

See face() for further information.

◆ vertices()

auto regina::detail::TriangulationBase< dim >::vertices ( ) const
inlineinherited

A dimension-specific alias for faces<0>().

This alias is available for all dimensions dim.

See faces() for further information.

◆ with02() [1/3]

std::optional< Triangulation< 3 > > regina::Triangulation< 3 >::with02 ( Edge< 3 > * e,
size_t t0,
size_t t1 ) const
inline

If possible, returns the triangulation obtained by performing a 0-2 move about the two specified triangles of this triangulation.

If such a move is not allowed, or if such a move would violate any facet locks, then this routine returns no value.

This triangulation will not be changed.

For more detail on 0-2 moves and when they can be performed, and for full details on what the arguments to this function mean, see move02(Edge<3>*, size_t, size_t).

Precondition
The given edge is a edge of this triangulation.
Parameters
ethe common edge of the two triangles about which to perform the move.
t0the number assigned to one of two triangles about which to perform the move.
t1the number assigned to the other triangle about which to perform the move.
Returns
The new triangulation obtained by performing the requested move, or no value if the requested move cannot be performed.
Author
Alex He

◆ with02() [2/3]

std::optional< Triangulation< 3 > > regina::Triangulation< 3 >::with02 ( EdgeEmbedding< 3 > e0,
int t0,
EdgeEmbedding< 3 > e1,
int t1 ) const
inline

If possible, returns the triangulation obtained by performing a 0-2 move about the two specified triangles of this triangulation.

If such a move is not allowed, or if such a move would violate any facet locks, then this routine returns no value.

This triangulation will not be changed.

For more detail on 0-2 moves and when they can be performed, and for full details on what the arguments to this function mean, see move02(EdgeEmbedding<3>, int, EdgeEmbedding<3>, int).

Precondition
The given embeddings refer to edges of this triangulation.
Parameters
e0an embedding of the common edge e of the two triangles about which to perform the move.
t0indicates one of the triangles about which to perform the move, with respect to the edge embedding e0; this must be 2 or 3.
e1another embedding of the edge e.
t1indicates the other triangle about which to perform the move, with respect to the edge embedding e1; this must be 2 or 3.
Returns
The new triangulation obtained by performing the requested move, or no value if the requested move cannot be performed.
Author
Alex He

◆ with02() [3/3]

std::optional< Triangulation< 3 > > regina::Triangulation< 3 >::with02 ( Triangle< 3 > * t0,
int e0,
Triangle< 3 > * t1,
int e1 ) const
inline

If possible, returns the triangulation obtained by performing a 0-2 move about the two given triangles of this triangulation.

If such a move is not allowed, or if such a move would violate any facet locks, then this routine returns no value.

This triangulation will not be changed.

For more detail on 0-2 moves and when they can be performed, and for full details on what the arguments to this function mean, see move02(Triangle<3>*, int, Triangle<3>*, int).

Precondition
The given triangles are both triangles of this triangulation.
Parameters
t0one of the two triangles about which to perform the move.
e0the edge at which t0 meets the other triangle t1; this must be 0, 1 or 2.
t1the other triangle about which to perform the move.
e1the edge at which t1 meets the other triangle t0; this must be 0, 1 or 2.
Returns
The new triangulation obtained by performing the requested move, or no value if the requested move cannot be performed.
Author
Alex He

◆ with20()

std::optional< Triangulation< dim > > regina::detail::TriangulationBase< dim >::with20 ( Face< dim, k > * f) const
inherited

If possible, returns the triangulation obtained by performing a 2-0 move about the given k-face of this triangulation.

If such a move is not allowed, or if such a move would violate any simplex and/or facet locks, then this routine returns no value.

This triangulation will not be changed.

For more detail on 2-0 moves and when they can be performed, see move20().

Precondition
The given k-face is a k-face of this triangulation.
Template Parameters
kthe dimension of the given face. This must be 0, 1 or 2, and must not exceed dim - 2.
Parameters
fthe k-face about which to perform the move.
Returns
The new triangulation obtained by performing the requested move, or no value if the requested move cannot be performed.

◆ with21()

std::optional< Triangulation< 3 > > regina::Triangulation< 3 >::with21 ( Edge< 3 > * e,
int edgeEnd ) const
inline

If possible, returns the triangulation obtained by performing a 2-1 move at the given end of the given edge of this triangulation.

If such a move is not allowed, or if such a move would violate any simplex and/or facet locks, then this routine returns no value.

This triangulation will not be changed.

For more detail on 2-1 moves and when they can be performed, see move21().

Precondition
The given edge is a edge of this triangulation.
Parameters
ethe edge about which to perform the move.
edgeEndindicates at which end of the edge e the move does not involve the adjacent tetrahedron; this should be 0 or 1. See move21() for details on exactly what this means.
Returns
The new triangulation obtained by performing the requested move, or no value if the requested move cannot be performed.

◆ with44()

std::optional< Triangulation< 3 > > regina::Triangulation< 3 >::with44 ( Edge< 3 > * e,
int axis ) const
inline

If possible, returns the triangulation obtained by performing a 4-4 move about the given edge of this triangulation.

If such a move is not allowed, or if such a move would violate any simplex and/or facet locks, then this routine returns no value.

This triangulation will not be changed.

For more detail on 4-4 moves and when they can be performed, see move44().

Precondition
The given edge is a edge of this triangulation.
Parameters
ethe edge about which to perform the move.
axisindicates which axis of the enclosing octahedron the four new tetrahedra should meet along; this must be 0 or 1. See move44() for details on exactly what this means.
Returns
The new triangulation obtained by performing the requested move, or no value if the requested move cannot be performed.

◆ withCloseBook()

std::optional< Triangulation< 3 > > regina::Triangulation< 3 >::withCloseBook ( Edge< 3 > * e) const
inline

If possible, returns the triangulation obtained by performing a book closing move about the given edge of this triangulation.

If such a move is not allowed, or if such a move would violate any facet locks, then this routine returns no value.

This triangulation will not be changed.

For more detail on book closing moves and when they can be performed, see closeBook().

Precondition
The given edge is an edge of this triangulation.
Parameters
ethe edge about which to perform the move.
Returns
The new triangulation obtained by performing the requested move, or no value if the requested move cannot be performed.

◆ withCollapseEdge()

std::optional< Triangulation< 3 > > regina::Triangulation< 3 >::withCollapseEdge ( Edge< 3 > * e) const
inline

If possible, returns the triangulation obtained by collapsing the given edge of this triangulation.

If such a move is not allowed, or if such a move would violate any simplex and/or facet locks, then this routine returns no value.

This triangulation will not be changed.

For more detail on edge collapse moves and when they can be performed, see collapseEdge().

Precondition
The given edge is an edge of this triangulation.
Parameters
ethe edge to collapse.
Returns
The new triangulation obtained by performing the requested move, or no value if the requested move cannot be performed.

◆ withOpenBook()

std::optional< Triangulation< 3 > > regina::Triangulation< 3 >::withOpenBook ( Triangle< 3 > * t) const
inline

If possible, returns the triangulation obtained by performing a book opening move about the given triangle of this triangulation.

If such a move is not allowed, or if such a move would violate any facet locks, then this routine returns no value.

This triangulation will not be changed.

For more detail on book opening moves and when they can be performed, see openBook().

Precondition
The given triangle is a triangle of this triangulation.
Parameters
tthe triangle about which to perform the move.
Returns
The new triangulation obtained by performing the requested move, or no value if the requested move cannot be performed.

◆ withPachner()

std::optional< Triangulation< dim > > regina::detail::TriangulationBase< dim >::withPachner ( Face< dim, k > * f) const
inherited

If possible, returns the triangulation obtained by performing a (dim + 1 - k)-(k + 1) Pachner move about the given k-face of this triangulation.

If such a move is not allowed, or if such a move would violate any simplex and/or facet locks, then this routine returns no value.

This triangulation will not be changed.

For more detail on Pachner moves and when they can be performed, see pachner().

Precondition
The given k-face is a k-face of this triangulation.
Template Parameters
kthe dimension of the given face. This must be between 0 and (dim) inclusive.
Parameters
fthe k-face about which to perform the move.
Returns
The new triangulation obtained by performing the requested move, or no value if the requested move cannot be performed.

◆ withShellBoundary()

std::optional< Triangulation< dim > > regina::detail::TriangulationBase< dim >::withShellBoundary ( Simplex< dim > * s) const
inherited

If possible, returns the triangulation obtained by performing a boundary shelling move on the given top-dimensional simplex of this triangulation.

If such a move is not allowed, or if such a move would violate any simplex and/or facet locks, then this routine returns no value.

This operation is only available in standard dimensions, since Regina's notion of "valid faces" is weaker in higher dimensions (due to the need to solve undecidable problems). See Face::isValid() for further discussion.

This triangulation will not be changed.

For more detail on boundary shelling moves and when they can be performed, see shellBoundary().

Precondition
The dimension dim is one of Regina's standard dimensions.
The given simplex is a simplex of this triangulation.
Parameters
sthe top-dimensional simplex upon which to perform the move.
Returns
The new triangulation obtained by performing the requested move, or no value if the requested move cannot be performed.

◆ writeDot()

void regina::detail::TriangulationBase< dim >::writeDot ( std::ostream & out,
bool labels = false ) const
inherited

Writes the dual graph of this triangulation in the Graphviz DOT language.

See dot() for further details on what this output contains.

This routine is equivalent to (but faster than) writing the string returned by dot() to the given output stream.

Python
Not present. Use dot() instead, which returns a string.
Parameters
outthe output stream to which to write.
labelsindicates whether graph vertices should be labelled with the corresponding top-dimensional simplex numbers.
See also
http://www.graphviz.org/

◆ writeTextLong()

void regina::detail::TriangulationBase< dim >::writeTextLong ( std::ostream & out) const
inherited

Writes a detailed text representation of this object to the given output stream.

Python
Not present. Use detail() instead.
Parameters
outthe output stream to which to write.

◆ writeTextShort()

void regina::detail::TriangulationBase< dim >::writeTextShort ( std::ostream & out) const
inherited

Writes a short text representation of this object to the given output stream.

Python
Not present. Use str() instead.
Parameters
outthe output stream to which to write.

◆ writeXMLBaseProperties()

void regina::detail::TriangulationBase< dim >::writeXMLBaseProperties ( std::ostream & out) const
protectedinherited

Writes a chunk of XML containing properties of this triangulation.

This routine covers those properties that are managed by this base class TriangulationBase and that have already been computed for this triangulation.

This routine is typically called from within Triangulation<dim>::writeXMLPacketData(). The XML elements that it writes are child elements of the tri element.

Parameters
outthe output stream to which the XML should be written.

◆ zeroTwoMove() [1/3]

bool regina::Triangulation< 3 >::zeroTwoMove ( Edge< 3 > * e,
size_t t0,
size_t t1,
bool ignored,
bool perform = true )
inline

Deprecated routine that tests for and optionally performs a 0-2 move about the two specified triangles of this triangulation.

For more detail on 0-2 moves and when they can be performed, and for full details on what the arguments to this function mean, see move02(Edge<3>*, size_t, size_t).

This routine will always check whether the requested move is legal and will not violate any facet locks (see Simplex<3>::lockFacet() for further details on facet locks). Note that this type of move can never violate a simplex lock, and so there is no need to check for those at all. If the move is allowed, and if the argument perform is true, this routine will also perform the move.

Deprecated
If you just wish to test whether such a move is possible, call has02(). If you wish to both check and perform the move, call move02().
Precondition
The given edge is an edge of this triangulation.
Parameters
ethe common edge of the two triangles about which to perform the move.
t0the number assigned to one of two triangles about which to perform the move.
t1the number assigned to the other triangle about which to perform the move.
ignoredan argument that is ignored. In earlier versions of Regina this argument controlled whether we check if the move can be performed; however, now this check is done always.
performtrue if we should actually perform the move, assuming the move is allowed.
Returns
true if and only if the requested move could be performed.
Author
Alex He

◆ zeroTwoMove() [2/3]

bool regina::Triangulation< 3 >::zeroTwoMove ( EdgeEmbedding< 3 > e0,
int t0,
EdgeEmbedding< 3 > e1,
int t1,
bool ignored,
bool perform = true )
inline

Deprecated routine that tests for and optionally performs a 0-2 move about the two specified triangles of this triangulation.

For more detail on 0-2 moves and when they can be performed, and for full details on what the arguments to this function mean, see move02(EdgeEmbedding<3>, int, EdgeEmbedding<3>, int).

This routine will always check whether the requested move is legal and will not violate any facet locks (see Simplex<3>::lockFacet() for further details on facet locks). Note that this type of move can never violate a simplex lock, and so there is no need to check for those at all. If the move is allowed, and if the argument perform is true, this routine will also perform the move.

Deprecated
If you just wish to test whether such a move is possible, call has02(). If you wish to both check and perform the move, call move02().
Precondition
The two given edge embeddings both refer to the same edge, which must be an edge of this triangulation.
Parameters
e0an embedding of the common edge e of the two triangles about which to perform the move.
t0indicates one of the triangles about which to perform the move, with respect to the edge embedding e0; this must be 2 or 3.
e1another embedding of the edge e.
t1indicates the other triangle about which to perform the move, with respect to the edge embedding e1; this must be 2 or 3.
ignoredan argument that is ignored. In earlier versions of Regina this argument controlled whether we check if the move can be performed; however, now this check is done always.
performtrue if we should actually perform the move, assuming the move is allowed.
Returns
true if and only if the requested move could be performed.
Author
Alex He

◆ zeroTwoMove() [3/3]

bool regina::Triangulation< 3 >::zeroTwoMove ( Triangle< 3 > * t0,
int e0,
Triangle< 3 > * t1,
int e1,
bool ignored,
bool perform = true )
inline

Deprecated routine that tests for and optionally performs a 0-2 move about the two given triangles of this triangulation.

For more detail on 0-2 moves and when they can be performed, and for full details on what the arguments to this function mean, see move02(Triangle<3>*, int, Triangle<3>*, int).

This routine will always check whether the requested move is legal and will not violate any facet locks (see Simplex<3>::lockFacet() for further details on facet locks). Note that this type of move can never violate a simplex lock, and so there is no need to check for those at all. If the move is allowed, and if the argument perform is true, this routine will also perform the move.

Deprecated
If you just wish to test whether such a move is possible, call has02(). If you wish to both check and perform the move, call move02().
Precondition
The given triangles are both triangles of this triangulation.
Parameters
t0one of the two triangles about which to perform the move.
e0the edge at which t0 meets the other triangle t1; this must be 0, 1 or 2.
t1the other triangle about which to perform the move.
e1the edge at which t1 meets the other triangle t0; this must be 0, 1 or 2.
ignoredan argument that is ignored. In earlier versions of Regina this argument controlled whether we check if the move can be performed; however, now this check is done always.
performtrue if we should actually perform the move, assuming the move is allowed.
Returns
true if and only if the requested move could be performed.
Author
Alex He

Member Data Documentation

◆ boundaryComponents_

MarkedVector<BoundaryComponent<dim> > regina::detail::TriangulationBase< dim >::boundaryComponents_
protectedinherited

The components that form the boundary of the triangulation.

◆ components_

MarkedVector<Component<dim> > regina::detail::TriangulationBase< dim >::components_
protectedinherited

The connected components that form the triangulation.

This list is only filled if/when the skeleton of the triangulation is computed.

◆ compressingDisc_

std::optional<bool> regina::Triangulation< 3 >::compressingDisc_

Does this 3-manifold contain a compressing disc?

◆ dimension

int regina::detail::TriangulationBase< dim >::dimension
staticconstexprinherited

A compile-time constant that gives the dimension of the triangulation.

◆ H1Bdry_

std::optional<AbelianGroup> regina::Triangulation< 3 >::H1Bdry_

First homology group of the boundary.

◆ H1Rel_

std::optional<AbelianGroup> regina::Triangulation< 3 >::H1Rel_

Relative first homology group of the triangulation with respect to the boundary.

◆ H2_

std::optional<AbelianGroup> regina::Triangulation< 3 >::H2_

Second homology group of the triangulation.

◆ haken_

std::optional<bool> regina::Triangulation< 3 >::haken_

Is this 3-manifold Haken? This property must only be stored for triangulations that are known to represent closed, connected, orientable, irreducible 3-manifolds.

◆ handlebody_

std::optional<ssize_t> regina::Triangulation< 3 >::handlebody_

Is this a triangulation of an orientable handlebody? If so, this stores the genus; if not, this stores -1.

◆ heldBy_

PacketHeldBy regina::PacketData< Triangulation< dim > >::heldBy_
protectedinherited

Indicates whether this Held object is in fact the inherited data for a PacketOf<Held>.

As a special case, this field is also used to indicate when a Triangulation<3> is in fact the inherited data for a SnapPeaTriangulation. See the PacketHeldBy enumeration for more details on the different values that this data member can take.

◆ irreducible_

std::optional<bool> regina::Triangulation< 3 >::irreducible_

Is this 3-manifold irreducible?

◆ nBoundaryFaces_

std::array<size_t, dim> regina::detail::TriangulationBase< dim >::nBoundaryFaces_
protectedinherited

The number of boundary faces of each dimension.

◆ negativeIdealBoundaryComponents_

std::optional<bool> regina::Triangulation< 3 >::negativeIdealBoundaryComponents_

Does the triangulation contain any boundary components that are ideal and have negative Euler characteristic?

◆ niceTreeDecomposition_

std::optional<TreeDecomposition> regina::Triangulation< 3 >::niceTreeDecomposition_

A nice tree decomposition of the face pairing graph of this triangulation.

◆ oneEfficient_

std::optional<bool> regina::Triangulation< 3 >::oneEfficient_

Is the triangulation one-efficient?

◆ simplices_

MarkedVector<Simplex<dim> > regina::detail::TriangulationBase< dim >::simplices_
protectedinherited

The top-dimensional simplices that form the triangulation.

◆ splittingSurface_

std::optional<bool> regina::Triangulation< 3 >::splittingSurface_

Does the triangulation have a normal splitting surface?

◆ threeSphere_

std::optional<bool> regina::Triangulation< 3 >::threeSphere_

Is this a triangulation of a 3-sphere?

◆ topologyLock_

uint8_t regina::TopologyLockable::topologyLock_ { 0 }
protectedinherited

The number of topology locks currently held on this object.

Any non-zero number of locks implies that "hook routines" that clear computed properties (as described in the class notes) will preserve properties that are purely topological.

◆ turaevViroCache_

TuraevViroSet regina::Triangulation< 3 >::turaevViroCache_

The set of Turaev-Viro invariants that have already been calculated.

See allCalculatedTuraevViro() for details.

◆ twoSphereBoundaryComponents_

std::optional<bool> regina::Triangulation< 3 >::twoSphereBoundaryComponents_

Does the triangulation contain any 2-sphere boundary components?

◆ TxI_

std::optional<bool> regina::Triangulation< 3 >::TxI_

Is this a triangulation of the product TxI?

◆ valid_

bool regina::detail::TriangulationBase< dim >::valid_
protectedinherited

Is this triangulation valid? See isValid() for details on what this means.

◆ zeroEfficient_

std::optional<bool> regina::Triangulation< 3 >::zeroEfficient_

Is the triangulation zero-efficient?


The documentation for this class was generated from the following file: