Regina 7.0 Calculation Engine
|
Represents a directed knot or link in the 3-sphere. More...
#include <link/link.h>
Public Member Functions | |
std::shared_ptr< PacketOf< Link > > | packet () |
Returns the packet that holds this data, if there is one. More... | |
std::shared_ptr< const PacketOf< Link > > | packet () const |
Returns the packet that holds this data, if there is one. More... | |
std::string | anonID () const |
A unique string ID that can be used in place of a packet ID. More... | |
std::string | str () const |
Returns a short text representation of this object. More... | |
std::string | utf8 () const |
Returns a short text representation of this object using unicode characters. More... | |
std::string | detail () const |
Returns a detailed text representation of this object. More... | |
Constructors and Destructors | |
Link ()=default | |
Constructs an empty link. More... | |
Link (size_t unknots) | |
Constructs the unlink with the given number of components. More... | |
Link (const Link ©) | |
Constructs a new copy of the given link. More... | |
Link (const Link ©, bool cloneProps) | |
Constructs a new copy of the given link, with the option of whether or not to clone its computed properties also. More... | |
Link (Link &&src) noexcept | |
Moves the given link into this new link. More... | |
Link (const std::string &description) | |
"Magic" constructor that tries to find some way to interpret the given string as a link. More... | |
~Link () | |
Destroys this link. More... | |
Crossings and Components | |
bool | isEmpty () const |
Determines whether this link is empty. More... | |
size_t | size () const |
Returns the number of crossings in this link. More... | |
size_t | countComponents () const |
Returns the number of components in this link. More... | |
Crossing * | crossing (size_t index) const |
Returns a pointer to the crossing at the given index within this link. More... | |
auto | crossings () const |
Returns an object that allows iteration through and random access to all crossings within this link. More... | |
StrandRef | component (size_t index) const |
Returns a strand in the given component of this link. More... | |
auto | components () const |
Returns an object that allows iteration through and random access to all components of this link. More... | |
StrandRef | strand (int id) const |
Returns the strand in the link with the given integer ID. More... | |
StrandRef | translate (const StrandRef &other) const |
Translates a strand reference for some other link into the corresponding strand reference for this link. More... | |
bool | connected (const Crossing *a, const Crossing *b) const |
Determines whether the two given crossings are connected in the underlying 4-valent graph of the link diagram. More... | |
bool | operator== (const Link &other) const |
Determines if this link diagram is combinatorially identical to the given link diagram. More... | |
bool | operator!= (const Link &other) const |
Determines if this link diagram is not combinatorially identical to the given link diagram. More... | |
Editing | |
Link & | operator= (const Link &src) |
Sets this to be a (deep) copy of the given link. More... | |
Link & | operator= (Link &&src) |
Moves the contents of the given link into this link. More... | |
void | swap (Link &other) |
Swaps the contents of this and the given link. More... | |
void | swapContents (Link &other) |
Deprecated routine that swaps the contents of this and the given link. More... | |
void | change (Crossing *c) |
Switches the upper and lower strands of the given crossing. More... | |
void | changeAll () |
Switches the upper and lower strands of every crossing in the diagram. More... | |
void | resolve (Crossing *c) |
Resolves the given crossing. More... | |
void | reflect () |
Converts this link into its reflection. More... | |
void | rotate () |
Rotates this link diagram, converting it into a different diagram of the same link. More... | |
void | reverse () |
Reverses the orientation of every component of this link. More... | |
bool | r1 (Crossing *crossing, bool check=true, bool perform=true) |
Tests for and/or performs a type I Reidemeister move to remove a crossing. More... | |
bool | r1 (StrandRef arc, int side, int sign, bool check=true, bool perform=true) |
Tests for and/or performs a type I Reidemeister move to add a new crossing. More... | |
bool | r2 (StrandRef arc, bool check=true, bool perform=true) |
Tests for and/or performs a type II Reidemeister move to remove two crossings. More... | |
bool | r2 (Crossing *crossing, bool check=true, bool perform=true) |
Tests for and/or performs a type II Reidemeister move to remove two crossings. More... | |
bool | r2 (StrandRef upperArc, int upperSide, StrandRef lowerArc, int lowerSide, bool check=true, bool perform=true) |
Tests for and/or performs a type II Reidemeister move to add two new crossings. More... | |
bool | r3 (StrandRef arc, int side, bool check=true, bool perform=true) |
Tests for and/or performs a type III Reidemeister move. More... | |
bool | r3 (Crossing *crossing, int side, bool check=true, bool perform=true) |
Tests for and/or performs a type III Reidemeister move. More... | |
bool | hasReducingPass () const |
Tests whether this knot has a pass move that will reduce the number of crossings. More... | |
void | selfFrame () |
Adds trivial twists to this link to ensure that each component has zero writhe. More... | |
bool | intelligentSimplify () |
Attempts to simplify the link diagram using fast and greedy heuristics. More... | |
bool | simplifyToLocalMinimum (bool perform=true) |
Uses type I and II Reidemeister moves to reduce the link monotonically to some local minimum number of crossings. More... | |
bool | simplifyExhaustive (int height=1, unsigned nThreads=1, ProgressTrackerOpen *tracker=nullptr) |
Attempts to simplify this knot diagram using a slow but exhaustive search through the Reidemeister graph. More... | |
template<typename Action , typename... Args> | |
bool | rewrite (int height, unsigned nThreads, ProgressTrackerOpen *tracker, Action &&action, Args &&... args) const |
Explores all knot diagrams that can be reached from this via Reidemeister moves, without exceeding a given number of additional crossings. More... | |
void | composeWith (const Link &other) |
Forms the composition of this with the given link. More... | |
Exporting Links | |
std::string | brief () const |
Outputs this link in Regina's own brief write-only format. More... | |
void | brief (std::ostream &out) const |
Writes this link in Regina's own brief format to the given output stream. More... | |
std::string | gauss () const |
Returns a classical Gauss code for this knot, presented as a string. More... | |
std::vector< int > | gaussData () const |
Returns a classical Gauss code for this knot, presented as a vector of integers. More... | |
void | gauss (std::ostream &out) const |
Writes a classical Gauss code for this knot to the given output stream. More... | |
std::string | orientedGauss () const |
Returns an oriented Gauss code for this knot, presented as a string. More... | |
std::vector< std::string > | orientedGaussData () const |
Returns an oriented Gauss code for this knot, presented as a vector of string tokens. More... | |
void | orientedGauss (std::ostream &out) const |
Writes an oriented Gauss code for this knot to the given output stream. More... | |
std::string | jenkins () const |
Exports this link using Bob Jenkins' text format, returning a single string. More... | |
std::vector< int > | jenkinsData () const |
Exports this link using Bob Jenkins' text format, returning a vector of integers. More... | |
void | jenkins (std::ostream &out) const |
Exports this link to the given output stream using Bob Jenkins' text format. More... | |
std::string | dt (bool alpha=false) const |
Exports this knot in either numerical or alphabetical Dowker-Thistlethwaite notation, returning a string. More... | |
std::vector< int > | dtData () const |
Exports this knot in numerical Dowker-Thistlethwaite notation, returning a vector of integers. More... | |
void | dt (std::ostream &out, bool alpha=false) const |
Writes this knot to the given output stream using Dowker-Thistlethwaite notation. More... | |
std::string | pd () const |
Returns a planar diagram code for this link, presented as a string. More... | |
std::vector< std::array< int, 4 > > | pdData () const |
Returns a planar diagram code for this link, presented as vector of 4-tuples. More... | |
void | pd (std::ostream &out) const |
Writes a planar diagram code for this link to the given output stream. More... | |
void | writePACE (std::ostream &out) const |
Outputs the underlying planar 4-valent multigraph using the PACE text format. More... | |
std::string | pace () const |
Returns a text representation of the underlying planar 4-valent multigraph, using the PACE text format. More... | |
std::string | dumpConstruction () const |
Returns C++ code that can be used to reconstruct this link. More... | |
std::string | knotSig (bool useReflection=true, bool useReversal=true) const |
Constructs the signature for this knot diagram. More... | |
void | writeTextShort (std::ostream &out) const |
Writes a short text representation of this link to the given output stream. More... | |
void | writeTextLong (std::ostream &out) const |
Writes a detailed text representation of this link to the given output stream. More... | |
Static Public Attributes | |
static constexpr const char * | jonesVar = "\u221At" |
The name of the variable used in the Jones polynomial, as returned by jones(). More... | |
static constexpr const char * | homflyAZVarX = "\u03B1" |
The name of the first variable used in the variant of the HOMFLY polynomial as returned by homflyAZ(). More... | |
static constexpr const char * | homflyAZVarY = "z" |
The name of the second variable used in the variant of the HOMFLY polynomial as returned by homflyAZ(). More... | |
static constexpr const char * | homflyLMVarX = "\U0001D4C1" |
The name of the first variable used in the variant of the HOMFLY polynomial as returned by homflyLM(). More... | |
static constexpr const char * | homflyLMVarY = "m" |
The name of the second variable used in the variant of the HOMFLY polynomial as returned by homflyLM(). More... | |
static constexpr const char * | homflyVarX = homflyAZVarX |
The name of the first variable used in the variant of the HOMFLY polynomial as returned by homfly(). More... | |
static constexpr const char * | homflyVarY = homflyAZVarY |
The name of the second variable used in the variant of the HOMFLY polynomial as returned by homfly(). More... | |
Protected Attributes | |
PacketHeldBy | heldBy_ |
Indicates whether this Held object is in fact the inherited data for a PacketOf<Held>. More... | |
Building Links | |
class | ModelLinkGraph |
class | Tangle |
class | XMLLinkCrossingsReader |
class | XMLLinkComponentsReader |
class | XMLWriter< Link > |
void | insertTorusLink (int p, int q, bool positive=true) |
Inserts a new (p, q) torus link into this link. More... | |
template<typename... Args> | |
static Link | fromData (std::initializer_list< int > crossingSigns, std::initializer_list< Args >... components) |
Creates a link from hard-coded information about its crossings and components. More... | |
template<typename SignIterator , typename ComponentIterator > | |
static Link | fromData (SignIterator beginSigns, SignIterator endSigns, ComponentIterator beginComponents, ComponentIterator endComponents) |
Creates a new link from information about its crossings and components. More... | |
static Link | fromKnotSig (const std::string &sig) |
Recovers a knot diagram from its signature. More... | |
static Link | fromSig (const std::string &sig) |
Alias for fromKnotSig(), to recover a knot diagram from its signature. More... | |
static Link | fromGauss (const std::string &str) |
Creates a new knot from a classical Gauss code, presented as a string. More... | |
template<typename Iterator > | |
static Link | fromGauss (Iterator begin, Iterator end) |
Creates a new knot from a classical Gauss code, presented as an integer sequence. More... | |
static Link | fromOrientedGauss (const std::string &str) |
Creates a new knot from an "oriented" variant of the Gauss code, presented as string. More... | |
template<typename Iterator > | |
static Link | fromOrientedGauss (Iterator begin, Iterator end) |
Creates a new knot from an "oriented" variant of the Gauss code, presented as a sequence of string tokens. More... | |
static Link | fromJenkins (const std::string &str) |
Creates a new link from Bob Jenkins' format, presented as a string. More... | |
static Link | fromJenkins (std::istream &in) |
Creates a new link from Bob Jenkins' format, read directly from an input stream. More... | |
template<typename Iterator > | |
static Link | fromJenkins (Iterator begin, Iterator end) |
Creates a new link from Bob Jenkins' format, presented as an integer sequence. More... | |
static Link | fromDT (const std::string &str) |
Creates a new knot from either alphabetical or numerical Dowker-Thistlethwaite notation, presented as a string. More... | |
template<typename Iterator > | |
static Link | fromDT (Iterator begin, Iterator end) |
Creates a new knot from numerical Dowker-Thistlethwaite notation, presented as an integer sequence. More... | |
static Link | fromPD (const std::string &str) |
Creates a new link from a planar diagram code, presented as a string. More... | |
template<typename Iterator > | |
static Link | fromPD (Iterator begin, Iterator end) |
Creates a new link from a planar diagram code, presented as a sequence of 4-tuples. More... | |
Invariants and Related Properties | |
bool | isAlternating () const |
Returns whether this knot diagram is alternating. More... | |
long | linking () const |
Returns the linking number of this link. More... | |
long | writhe () const |
Returns the writhe of this link diagram. More... | |
long | writheOfComponent (StrandRef component) const |
Returns the writhe of a single component of this link diagram. More... | |
long | writheOfComponent (size_t index) const |
Returns the writhe of a single component of this link diagram. More... | |
Triangulation< 3 > | complement (bool simplify=true) const |
Returns an ideal triangulation of the complement of this link in the 3-sphere. More... | |
Link | parallel (int k, Framing framing=FRAMING_SEIFERT) const |
Returns k cables of this link, all parallel to each other using the given framing. More... | |
const Laurent< Integer > & | bracket (Algorithm alg=ALG_DEFAULT, ProgressTracker *tracker=nullptr) const |
Returns the Kauffman bracket polynomial of this link diagram. More... | |
bool | knowsBracket () const |
Is the Kauffman bracket polynomial of this link diagram already known? See bracket() for further details. More... | |
const Laurent< Integer > & | jones (Algorithm alg=ALG_DEFAULT, ProgressTracker *tracker=nullptr) const |
Returns the Jones polynomial of this link, but with all exponents doubled. More... | |
bool | knowsJones () const |
Is the Jones polynomial of this link diagram already known? See jones() for further details. More... | |
const Laurent2< Integer > & | homflyAZ (Algorithm alg=ALG_DEFAULT, ProgressTracker *tracker=nullptr) const |
Returns the HOMFLY polynomial of this link, as a polynomial in alpha and z. More... | |
const Laurent2< Integer > & | homflyLM (Algorithm alg=ALG_DEFAULT, ProgressTracker *tracker=nullptr) const |
Returns the HOMFLY polynomial of this link, as a polynomial in l and m. More... | |
const Laurent2< Integer > & | homfly (Algorithm alg=ALG_DEFAULT, ProgressTracker *tracker=nullptr) const |
Returns the HOMFLY polynomial of this link, as a polynomial in alpha and z. More... | |
bool | knowsHomfly () const |
Is the HOMFLY polynomial of this link diagram already known? See homflyAZ() and homflyLM() for further details. More... | |
GroupPresentation | group (bool simplify=true) const |
Returns the group of this link; that is, the fundamental group of the link exterior. More... | |
const TreeDecomposition & | niceTreeDecomposition () const |
Returns a nice tree decomposition of the planar 4-valent multigraph formed by this link diagram. More... | |
void | useTreeDecomposition (TreeDecomposition td) |
Instructs Regina to use the given tree decomposition as the starting point whenever it needs a tree decomposition for this link. More... | |
static Laurent2< Integer > | homflyAZtoLM (Laurent2< Integer > homflyAZ) |
Converts between the (alpha, z) and (l, m) representations of the HOMFLY polynomial. More... | |
Represents a directed knot or link in the 3-sphere.
This class supports links with any number of components (including zero), and it also supports components with no crossings (which form additional unknot components of the overall link).
Since Regina 7.0, this is no longer a "packet type" that can be inserted directly into the packet tree. Instead a Link is now a standalone mathematatical object, which makes it slimmer and faster for ad-hoc use. The consequences of this are:
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.
|
default |
Constructs an empty link.
This will have zero components.
|
inline |
Constructs the unlink with the given number of components.
unknots | the number of (unknotted) components in the new unlink. |
|
inline |
Constructs a new copy of the given link.
This will clone any computed properties (such as Jones polynomial and so on) of the given link also. If you want a "clean" copy that resets all properties to unknown, you can use the two-argument copy constructor instead.
copy | the link to copy. |
regina::Link::Link | ( | const Link & | copy, |
bool | cloneProps | ||
) |
Constructs a new copy of the given link, with the option of whether or not to clone its computed properties also.
copy | the link to copy. |
cloneProps | true if this should also clone any computed properties of the given link (such as Jones polynomial and so on), or false if the new link should have all properties marked as unknown. |
|
noexcept |
Moves the given link into this new link.
This is a fast (constant time) operation.
All crossings that belong to src will be moved into this link, and so any Crossing pointers or StrandRef object will remain valid. Likewise, all cached properties will be moved into this link.
The link that is passed (src) will no longer be usable.
noexcept
, and in particular does not fire any change events. This is because this link 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).src | the link to move. |
regina::Link::Link | ( | const std::string & | description | ) |
"Magic" constructor that tries to find some way to interpret the given string as a link.
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.
InvalidArgument | Regina could not interpret the given string as representing a link using any of the supported string types. |
description | a string that describes a knot or link. |
|
inline |
Destroys this link.
The Crossing objects contained in this link will also be destroyed.
|
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:
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.
See Packet::internalID() for further details.
const Laurent< Integer > & regina::Link::bracket | ( | Algorithm | alg = ALG_DEFAULT , |
ProgressTracker * | tracker = nullptr |
||
) | const |
Returns the Kauffman bracket polynomial of this link diagram.
Note that the bracket polynomial is not an invariant - it is preserved under Reidemeister moves II and III, but not I.
If this is the empty link, then this routine will return the zero polynomial.
Bear in mind that each time the link changes, all of its polynomials will be deleted. Thus the reference that is returned from this routine should not be kept for later use. Instead, bracket() should be called again; this will be instantaneous if the bracket polynomial has already been calculated.
If this polynomial 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 numbers of crossings.
Since Regina 7.0, this routine will not return until the polynomial 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.
alg | the algorithm with which to compute the polynomial. If you are not sure, the default (ALG_DEFAULT) is a safe choice. If you wish to specify a particular algorithm, there are currently two choices: ALG_NAIVE is a slow algorithm that computes the Kauffman bracket by resolving all crossings in all possible ways, and ALG_TREEWIDTH uses a fixed-parameter tractable treewidth-based algorithm. |
tracker | a progress tracker through which progress will be reported, or null if no progress reporting is required. |
std::string regina::Link::brief | ( | ) | const |
Outputs this link in Regina's own brief write-only format.
This format is concise, but contains enough information to manually reconstruct the complete link diagram.
This format cannot (yet) be used to read links back into Regina, and so it is not good for external storage, or for passing links between different programs (or even different instances of Regina). It was originally designed for use with the test suite, where it was used to ensure that links with being created and/or manipulated correctly.
The output will contain the following elements, separated by single spaces:
+
or -
), concatenated together, giving the signs of the crossings in order from crossing 0 to crossing size()-1;( a b c ... )
, indicating the crossings that are encountered as we follow the component in the forward direction from its starting strand. Each element a, b, c and so on will be written in the format used by the StrandRef class: either ^n
when passing over crossing n, or _n
when passing under crossing n.For example, the Whitehead link as returned by ExampleLink.whitehead() will give the following brief output:
--++- ( ^0 _1 ^4 _3 ^2 _4 ) ( _0 ^1 _2 ^3 )
As a special case, if the link contains no crossings, then the output will not begin with a space; instead it will simply be a sequence of the form ( ) ( ) ... ( )
.
The string will not end in a newline.
There is also a variant of brief() that writes directly to an output stream.
void regina::Link::brief | ( | std::ostream & | out | ) | const |
Writes this link in Regina's own brief format to the given output stream.
See brief() for a full description of Regina's brief format, as well as its limitations.
The output from this routine is precisely the string that would be returned by brief(). In particular, the output does not contain any newlines.
See also brief(), which returns the brief format as a string.
out | the output stream to which to write. |
void regina::Link::change | ( | Crossing * | c | ) |
Switches the upper and lower strands of the given crossing.
c | the crossing to change. |
void regina::Link::changeAll | ( | ) |
Switches the upper and lower strands of every crossing in the diagram.
This operation corresponds to reflecting the link diagram through the plane on which it is drawn.
|
inline |
Returns an ideal triangulation of the complement of this link in the 3-sphere.
The triangulation will have one ideal vertex for each link component. Assuming you pass simplify as true
(the default), there will typically be no internal vertices; however, this is not guaranteed.
Initially, each tetrahedron will be oriented according to a right-hand rule: the thumb of the right hand points from vertices 0 to 1, and the fingers curl around to point from vertices 2 to 3. If you pass simplify as true
, then Regina will attempt to simplify the triangulation to as few tetrahedra as possible: this may relabel the tetrahedra, though their orientations will be preserved.
This is the same triangulation that would be produced by passing this link to the Triangulation<3> constructor.
simplify | true if and only if the triangulation of the complement should be simplified to use as few tetrahedra as possible. |
|
inline |
Returns a strand in the given component of this link.
For each component of the link, this routine returns a "starting strand". You can traverse the entire component by beginning at this starting strand and repeatedly incrementing it through a routine such as StrandRef::operator++ or StrandRef::next().
If a component has no crossings (which means it must be a separate unknot component), then this routine will return a null reference (i.e., StrandRef::crossing() will return null
).
index | the index of the requested component. This must be between 0 and countComponents()-1 inclusive. |
|
inline |
Returns an object that allows iteration through and random access to all components of this link.
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 C++11 range-based for
loops. Each element of the list will be a starting strand for some components; more precisely, iterating through this list is equivalent to calling component(0)
, component(1)
, ..., component(countComponents()-1)
in turn. As an example, your code might look like:
The object that is returned will remain up-to-date and valid for as long as the link exists: even as components are added and/or removed, it will always reflect the components that are currently in the link. Nevertheless, it is recommended to treat this object as temporary only, and to call components() again each time you need it.
void regina::Link::composeWith | ( | const Link & | other | ) |
Forms the composition of this with the given link.
This link will be altered directly.
Specifically, the first component of the given link will be grafted into the first component of this link, in a way that preserves orientations and crossing signs. If the given link has any additional components, then they will be copied into this link directly with no modification.
This routine may be expanded in future versions of Regina to allow more flexibility (in particular, to allow you to choose which components of the two links to graft together, and/or at which strands to graft them).
If either link is empty (i.e., contains no components at all), then the result will simply be a clone of the other link (with no composition operation performed).
It is allowed to pass this link as other.
other | the link with which this should be composed. |
Determines whether the two given crossings are connected in the underlying 4-valent graph of the link diagram.
Here "the underlying 4-valent graph" means the multigraph whose vertices are the crossings and whose edges are the arcs between crossings. In particular
a | the first of the two crossings to examine. |
b | the second of the two crossings to examine. |
true
if and only if the two given crossings are connected.
|
inline |
Returns the number of components in this link.
|
inline |
Returns a pointer to the crossing at the given index within this link.
For a link with n crossings, the crossings are numbered from 0 to n-1 inclusive.
index | the index of the requested crossing. This must be between 0 and size()-1 inclusive. |
|
inline |
Returns an object that allows iteration through and random access to all crossings within this link.
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 C++11 range-based for
loops. Note that the elements of the list will be pointers, so your code might look like:
The object that is returned will remain up-to-date and valid for as long as the link exists: even as crossings are added and/or removed, it will always reflect the crossings that are currently in the link. Nevertheless, it is recommended to treat this object as temporary only, and to call crossings() again each time you need it.
|
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.
std::string regina::Link::dt | ( | bool | alpha = false | ) | const |
Exports this knot in either numerical or alphabetical Dowker-Thistlethwaite notation, returning a string.
Like classical Gauss codes, Dowker-Thistlethwaite notation essentially describes the 4-valent graph of a knot but not the particular embedding in the plane. It comes with two major restrictions:
If you need a code that specifies the knot uniquely and/or that is fast to parse, consider using the oriented Gauss code instead, which resolves both of these issues.
For an n-crossing knot, Regina supports two variants of Dowker-Thistlethwaite notation:
a
,b
,c
,...), and replacing negative integers (-2,-4,-6,...) with upper-case letters (A
,B
,C
,...). This alphabetical variant can only be used for knots with 26 crossings or fewer; for larger knots this routine will throw an exception if the alphabetical variant is requested.As an example, you can describe the trefoil using numerical Dowker-Thistlethwaite notation as:
4 6 2
In alphabetical Dowker-Thistlethwaite notation, this becomes:
bca
Currently Regina only supports Dowker-Thistlethwaite codes for knots, not empty or multiple component links. If this link does not have precisely one component, then this routine will throw an exception. It is possible that in future versions of Regina, Dowker-Thistlethwaite codes will be expanded to cover all possible link diagrams (hence the choice of NotImplemented as the exception type).
For numerical Dowker-Thistlethwaite notation, this routine will format the list of integers as a string. The integers will be separated by single spaces, and there will be no newlines. For alphabetical Dowker-Thistlethwaite notation, the string that is returned will not contain any whitespace at all.
For the numerical variant, the routine dtData() returns this same data in machine-readable format (as a C++ vector), instead of the human-readable format used here (a string). There is also another variant of dt() that can write either the numerical or the alphabetical variant directly to an output stream.
NotImplemented | Either this link is empty or has multiple components, or alpha is true and it has more than 26 crossings. |
alpha | true to use alphabetical notation, or false (the default) to use numerical notation. |
void regina::Link::dt | ( | std::ostream & | out, |
bool | alpha = false |
||
) | const |
Writes this knot to the given output stream using Dowker-Thistlethwaite notation.
See dt(bool) for a full description of Dowker-Thistlethwaite notation as it is used in Regina, as well as its limitations.
This routine can write either numerical or alphabetical Dowker-Thistlethwaite notation, as indicated by the optional argument alpha.
The output from this routine is precisely the string that would be returned by dt(bool). In particular, the output does not contain any newlines.
See also dtBool(bool), which can export either the numerical or alphabetical variant of Dowker-Thistlethwaite notation as a human-readable string, and dtData(), which exports the numerical variant only as a machine-readable sequence of integers.
NotImplemented | Either this link is empty or has multiple components, or alpha is true and it has more than 26 crossings. |
out | the output stream to which to write. |
alpha | true to use alphabetical notation, or false (the default) to use numerical notation. |
std::vector< int > regina::Link::dtData | ( | ) | const |
Exports this knot in numerical Dowker-Thistlethwaite notation, returning a vector of integers.
See dt(bool) for a full description of Dowker-Thistlethwaite notation as it is used in Regina, as well as its limitations.
Although Regina can work with both the numerical and alphabetical variants of Dowker-Thistlethwaite notation, this dtData() routine exports the numerical variant only. If you wish to export the alphabetical variant, you can call dt(true)
.
This routine returns machine-readable data (as a C++ vector); in contrast, calling dt()
returns the same integer sequence in human-readable format (as a string).
NotImplemented | This link is empty or has multiple components. |
std::string regina::Link::dumpConstruction | ( | ) | const |
Returns C++ code that can be used to reconstruct this link.
This code will call Link::fromData(), passing a series of hard-coded C++11 initialiser lists.
The main purpose of this routine is to generate these hard-coded initialiser lists, which can be tedious and error-prone to write by hand.
|
static |
Creates a new link from information about its crossings and components.
This routine is an analogue to the variant of fromData() that takes C++11 initialiser lists; however, here the input data may be constructed at runtime (which makes it accessible to Python, amongst other things).
For the purposes of this routine, we number the crossings 1, 2, ..., n. The information that you must pass to this routine is the following:
for
loops (so standard C++ container classes such as std::vector<int> and std::list<int> are be fine).Be aware that, once the link has been constructed, the crossings 1, ..., n will have been reindexed as 0, ..., n-1 (since every Link object numbers its crossings starting from 0).
As an example, Python users can construct the left-hand trefoil and the Hopf link as follows:
InvalidArgument | a link could not be reconstructed from the given data. |
[[...]]
with a single list [...]
.beginSigns | the beginning of the list of crossing signs. |
endSigns | a past-the-end iterator indicating the end of the list of crossing signs. |
beginComponents | the beginning of the list of containers describing each link component. |
endComponents | a past-the-end iterator indicating the end of the list of link components. |
|
static |
Creates a link from hard-coded information about its crossings and components.
This routine takes a series of C++11 initialiser lists (each a list of integers), which makes it useful for creating hard-coded examples directly in C++ code.
For the purposes of this routine, we number the crossings 1, 2, ..., n. The lists that you must pass to this routine are as follows:
Be aware that, once the link has been constructed, the crossings 1, ..., n will have been reindexed as 0, ..., n-1 (since every Link object numbers its crossings starting from 0).
As an example, you can construct the left-hand trefoil and the Hopf link as follows:
InvalidArgument | a link could not be reconstructed from the given data. |
crossingSigns | a list containing the signs of the crossings; each sign must be either +1 or -1. |
components | one list for each link component that describes the crossings that are visited along that component, as described in the detailed notes above. |
|
static |
Creates a new knot from either alphabetical or numerical Dowker-Thistlethwaite notation, presented as a string.
Dowker-Thistlethwaite notation essentially describes the 4-valent graph of a knot but not the particular embedding in the plane. As a result, there can be topological ambiguities when a knot is reconstructed from Dowker-Thistlethwaite notation; these are described in the warnings below.
Dowker-Thistlethwaite notation comes in two forms: numerical and alphabetical. For an n-crossing knot, the numerical form is a sequence of n even signed integers, and the alphabetical form is a sequence of n case-sensitive letters. As an example, you can construct the trefoil using either of the following strings:
4 6 2 bca
See dt(bool) for a full description of Dowker-Thistlethwaite notation as it is used in Regina, as well as its limitations.
There are two variants of this routine. This variant takes a single string, which is either (i) the alphabetical notation, in which any whitespace within the string will be ignored; or (ii) the numerical notation, in which the integers are combined together and separated by whitespace. The other variant of this routine is only for numerical Dowker-Thistlethwaite notation, and it takes a sequence of integers defined by a pair of iterators.
In this variant (the string variant), the string may contain additional leading or trailing whitespace; moreover, for numerical Dowker-Thistlethwaite notation, the exact form of the whitespace that separates the integers does not matter.
InvalidArgument | the given string was not a valid Dowker-Thistlethwaite code for a knot. As noted above, the checks performed here are not exhaustive. |
str | either the alphabetical or numerical Dowker-Thistlethwaite notation for a knot, as described above. |
|
static |
Creates a new knot from numerical Dowker-Thistlethwaite notation, presented as an integer sequence.
See dt(bool) for a full description of Dowker-Thistlethwaite notation as it is used in Regina, and see fromDT(const std::string&) for a detailed discussion of how Regina reconstructs knots from such notation.
This routine is a variant of fromDT(const std::string&) which, instead of taking a human-readable string, takes a machine-readable sequence of integers. This sequence is given by passing a pair of begin/end iterators.
This variant of fromDT() can only work with numerical Dowker-Thistlethwaite notation. Regina does understand alphabetic Dowker-Thistlethwaite notation, but for this you will need to use the string-based variant of fromDT().
InvalidArgument | the given sequence was not a valid Dowker-Thistlethwaite code for a knot. As noted above, the checks performed here are not exhaustive. |
begin | an iterator that points to the beginning of the sequence of integers for the Dowker-Thistlethwaite notation for a knot. |
end | an iterator that points past the end of the sequence of integers for the Dowker-Thistlethwaite notation for a knot. |
|
static |
Creates a new knot from a classical Gauss code, presented as a string.
Classical Gauss codes essentially describe the 4-valent graph of a knot but not the particular embedding in the plane. As a result, there can be topological ambiguities when a knot is reconstructed from a gauss code; these are described in the warnings below.
The Gauss code for an n-crossing knot is described by a sequence of 2n positive and negative integers. As an example, you can construct the trefoil using the code:
1 -2 3 -1 2 -3
See gauss() for a full description of classical Gauss codes as they are used in Regina, as well as their limitations.
Regina imposes the following restrictions when reconstructing a knot from a classical Gauss code:
Be aware that, once the knot has been constructed, the crossings 1, ..., n will have been reindexed as 0, ..., n-1 (since every Link object numbers its crossings starting from 0).
There are two variants of this routine. This variant takes a single string, where the integers have been combined together and separated by whitespace. The other variant takes a sequence of integers, defined by a pair of iterators.
In this variant (the string variant), the exact form of the whitespace does not matter, and additional whitespace at the beginning or end of the string is allowed.
InvalidArgument | the given string was not a valid classical Gauss code for a knot. As noted above, the checks performed here are not exhaustive. |
str | a classical Gauss code for a knot, as described above. |
|
static |
Creates a new knot from a classical Gauss code, presented as an integer sequence.
See gauss() for a full description of classical Gauss codes as they are used in Regina, and see fromGauss(const std::string&) for a detailed discussion of how Regina reconstructs knots from such codes.
This routine is a variant of fromGauss(const std::string&) which, instead of taking a human-readable string, takes a machine-readable sequence of integers. This sequence is given by passing a pair of begin/end iterators.
InvalidArgument | the given sequence was not a valid classical Gauss code for a knot. As noted above, the checks performed here are not exhaustive. |
begin | an iterator that points to the beginning of the sequence of integers for a classical Gauss code. |
end | an iterator that points past the end of the sequence of integers for a classical Gauss code. |
|
static |
Creates a new link from Bob Jenkins' format, presented as a string.
Jenkins' format overcomes the limitations of classical Gauss codes by encoding all of the data needed to quickly and correctly reconstruct a link diagram. It can work with links as well as knots.
In Jenkins' format, a link is described by a sequence of integers. As an example, you could construct the Hopf link using the sequence:
2 2 0 1 1 -1 2 0 -1 1 1 0 1 1 1
See jenkins() for a full description of Jenkins' format (and in particular, what these integers represent).
There are three variants of this routine. This variant takes a single string, where the integers have been combined together and separated by whitespace. The other variants take (i) a sequence of integers defined by a pair of iterators, or (ii) an input stream from which the integers will be read.
In this variant (the string variant), the exact form of the whitespace does not matter, and additional whitespace at the beginning or end of the string is allowed.
InvalidArgument | the given string was not a valid encoding of a link in Jenkins' format. As noted above, the checks performed here are not exhaustive. |
str | a string describing a link in Jenkins' format, as described above. |
|
static |
Creates a new link from Bob Jenkins' format, presented as an integer sequence.
See jenkins() for a full description of Bob Jenkins' format as it is used in Regina, and see fromJenkins(const std::string&) for a detailed discussion of how Regina reconstructs links from this format.
This routine is a variant of fromJenkins(const std::string&) which, instead of taking a human-readable string, takes a machine-readable sequence of integers. This sequence is given by passing a pair of begin/end iterators.
InvalidArgument | the given sequence was not a valid encoding of a link in Jenkins' format. As noted above, the checks performed here are not exhaustive. |
begin | an iterator that points to the beginning of the sequence of integers that describes a link. |
end | an iterator that points past the end of the sequence of integers that describes a link. |
|
static |
Creates a new link from Bob Jenkins' format, read directly from an input stream.
See jenkins() for a full description of Bob Jenkins' format as it is used in Regina, and see fromJenkins(const std::string&) for a detailed discussion of how Regina reconstructs links from this format.
This routine is a variant of fromJenkins(const std::string&) which, instead of taking a string as input, takes an input stream from which the sequence of integers describing the link will be read.
Once this routine reads the integers that describe the link, or as soon as it encounters an error (e.g., invalid input data), it will stop reading and leave the remainder of the input stream untouched. This means that the stream may contain additional material, which can be read by the user after this routine has finished.
InvalidArgument | the given input was not a valid encoding of a link in Jenkins' format. As noted above, the checks performed here are not exhaustive. |
in | an input stream that begins with a sequence of integers separated by whitespace that describes a link. |
|
static |
Recovers a knot diagram from its signature.
See knotSig() for more information on knot signatures.
Calling knotSig() followed by fromKnotSig() is not guaranteed to produce an identical knot diagram to the original, but it is guaranteed to produce one that is related by relabelling, rotation, and optionally (according to the arguments that were passed to knotSig()) reflection and/or reversal.
InvalidArgument | the given string was not a valid knot signature. |
sig | the signature of the knot diagram to construct. Note that signatures are case-sensitive. |
|
static |
Creates a new knot from an "oriented" variant of the Gauss code, presented as string.
Oriented gauss codes overcome the limitations of classical Gauss codes by encoding all of the data needed to quickly and correctly reconstruct a knot diagram.
The oriented Gauss code for an n-crossing knot is described by a sequence of 2n string tokens. As an example, you can construct the left-hand trefoil using the code:
+>1 -<2 +>3 -<1 +>2 -<3
See orientedGauss() for a full description of oriented Gauss codes as they are used in Regina (and in particular, what these tokens represent).
Regina imposes the following restrictions when reconstructing a knot from an oriented Gauss code:
Be aware that, once the knot has been constructed, the crossings 1, ..., n will have been reindexed as 0, ..., n-1 (since every Link object numbers its crossings starting from 0).
There are two variants of this routine. This variant takes a single string, where the tokens have been combined together and separated by whitespace. The other variant takes a sequence of tokens, defined by a pair of iterators.
In this variant (the string variant), the exact form of the whitespace does not matter, and additional whitespace at the beginning or end of the string is allowed.
InvalidArgument | the given string was not a valid oriented Gauss code for a knot. As noted above, the checks performed here are not exhaustive. |
str | an "oriented" Gauss code for a knot, as described above. |
|
static |
Creates a new knot from an "oriented" variant of the Gauss code, presented as a sequence of string tokens.
See orientedGauss() for a full description of oriented Gauss codes as they are used in Regina, and see fromOrientedGauss(const std::string&) for a detailed discussion of how Regina reconstructs knots from such codes.
This routine is a variant of fromOrientedGauss(const std::string&) which, instead of taking a human-readable string, takes a machine-readable sequence of string tokens. This sequence is given by passing a pair of begin/end iterators.
The tokens in the input sequence should be the individual tokens of the form +<k
, -<k
, +>k
or ->k
that would normally be joined with whitespace to form a complete oriented Gauss code. For example, to describe the left-hand trefoil, the input sequence could be a vector containing the six tokens:
{ "+>1", "-<2", "+>3", "-<1", "+>2", "-<3" }
Each individual token should not contain any whitespace; otherwise this routine may fail to parse the token(s) and could return null
as a result.
const char*
) or a C++-style string (which can be cast to const std::string&
).InvalidArgument | the given sequence was not a valid oriented Gauss code for a knot. As noted above, the checks performed here are not exhaustive. |
begin | an iterator that points to the beginning of the sequence of tokens for an "oriented" Gauss code. |
end | an iterator that points past the end of the sequence of tokens for an "oriented" Gauss code. |
|
static |
Creates a new link from a planar diagram code, presented as a string.
Planar diagram codes overcome the limitations of classical Gauss codes by encoding the local information at each crossing, though they do introduce their own (less severe) ambiguities and computational difficulties, as described in the warnings below. They can work with links as well as knots, though they cannot encode zero-crossing unknot components.
A planar diagram code for an n-crossing link is formed from a sequence of n 4-tuples of integers. An example, you can construct the right-handed trefoil using the sequence:
[[1, 5, 2, 4], [3, 1, 4, 6], [5, 3, 6, 2]]
See pd() for a full description of planar diagram codes (and in particular, what these integers represent).
Regina imposes the following restrictions when reconstructing a link from a planar diagram code:
When Regina builds the resulting link, it numbers the crossings and components (but not the strands). It will do this as follows:
There are two variants of this routine. This variant takes a single string containing all 4n integers (see below for how this string may be formatted). The other variant takes a sequence of 4-tuples of integers, defined by a pair of iterators.
In this variant (the string variant), the integers may be separated by any combination of the following:
PD
, X
, Xp
, Xm
and P
, which are used by other sources (such as the Knot Atlas), but which are ignored here.Thus the following strings all describe the same sequence:
[[1, 5, 2, 4], [3, 1, 4, 6], [5, 3, 6, 2]] PD[X[1, 5, 2, 4], X[3, 1, 4, 6], X[5, 3, 6, 2]] 1 5 2 4 3 1 4 6 5 3 6 2
The string may containin separators (as defined above) at the beginning and/or the end; these will be ignored.
Note that some sources (again, such as the Knot Atlas) use the special symbols Xp
, Xm
and P
to change the meaning of the tuples. Regina does not attribute any meaning to these symbols, and will treat them as nothing more than separators.
InvalidArgument | the given string was not a valid planar diagram code. As noted above, the checks performed here are not exhaustive. |
str | a planar diagram code for a link, as described above. |
|
static |
Creates a new link from a planar diagram code, presented as a sequence of 4-tuples.
See pd() for a full description of planar diagram codes as they are used in Regina, and see fromPD(const std::string&) for a detailed discussion of how Regina reconstructs links from such codes.
This routine is a variant of fromPD(const std::string&) which, instead of taking a human-readable string, takes a machine-readable sequence of 4-tuples of integers. This sequence is given by passing a pair of begin/end iterators.
(*it)[0]
, (*it)[1]
, (*it)[2]
and (*it)[3]
will give the elements of the corresponding 4-tuple, which can then be treated as native C++ integers.InvalidArgument | the given sequence was not a valid planar diagram code. As noted above, the checks performed here are not exhaustive. |
begin | an iterator that points to the beginning of the sequence of 4-tuples for a planar diagram code. |
end | an iterator that points past the end of the sequence of 4-tuples for a planar diagram code. |
|
inlinestatic |
Alias for fromKnotSig(), to recover a knot diagram from its signature.
This alias fromSig() is provided to assist with generic code that can work with both knots and triangulations.
See fromKnotSig() for further details.
InvalidArgument | the given string was not a valid knot signature. |
sig | the signature of the knot diagram to construct. Note that signatures are case-sensitive. |
std::string regina::Link::gauss | ( | ) | const |
Returns a classical Gauss code for this knot, presented as a string.
Classical Gauss codes essentially describe the 4-valent graph of a knot but not the particular embedding in the plane. These codes come with two major restrictions:
If you need a code that specifies the knot uniquely and/or that is fast to parse, consider using the oriented Gauss code instead, which resolves both of these issues.
A Gauss code for an n-crossing knot is described by a sequence of 2n positive and negative integers, representing strands that pass over and under crossings respectively. The code is constructed as follows:
k
if you pass over the crossing, or -k
if you pass under the crossing.As an example, you can represent the trefoil using the code:
1 -2 3 -1 2 -3
Currently Regina only supports Gauss codes for knots, not empty or multiple component links. If this link does not have precisely one component, then this routine will throw an exception. It is possible that in future versions of Regina, Gauss codes will be expanded to cover all possible link diagrams (hence the choice of NotImplemented as the exception type).
This routine formats the list of integers as a string. The integers will be separated by single spaces, and there will be no newlines.
The routine gaussData() returns this same data in machine-readable format (as a C++ vector), instead of the human-readable format used here (a string). There is also another variant of gauss() that writes directly to an output stream.
NotImplemented | This link is empty or has multiple components. |
void regina::Link::gauss | ( | std::ostream & | out | ) | const |
Writes a classical Gauss code for this knot to the given output stream.
See gauss() for a full description of classical Gauss codes as they are used in Regina, as well as their limitations.
The output from this routine is precisely the string that would be returned by gauss(). In particular, the output does not contain any newlines.
See also gauss(), which returns the Gauss code as a human-readable string, and gaussData(), which returns it as a machine-readable sequence of integers.
NotImplemented | This link is empty or has multiple components. |
out | the output stream to which to write. |
std::vector< int > regina::Link::gaussData | ( | ) | const |
Returns a classical Gauss code for this knot, presented as a vector of integers.
See gauss() for a full description of classical Gauss codes as they are used in Regina, as well as their limitations.
This routine returns machine-readable data (as a C++ vector); in contrast, gauss() returns the same data in human-readable format (as a string).
NotImplemented | This link is empty or has multiple components. |
GroupPresentation regina::Link::group | ( | bool | simplify = true | ) | const |
Returns the group of this link; that is, the fundamental group of the link exterior.
This routine builds the Wirtinger presentation, where all relations are some variant of the form xy=yz
.
If you pass simplify as false
, it will leave the presentation in exactly this form (i.e., the Wirtinger presentation), and not simplify it further. If you pass simplify as true
(the default), this routine will attempt to simplify the group presentation before returning.
Currently this group is not cached; instead it is reconstructed every time this function is called. This behaviour may change in future versions of Regina.
bool regina::Link::hasReducingPass | ( | ) | const |
Tests whether this knot has a pass move that will reduce the number of crossings.
Currently this routine is only available for knots, not multiple-component links.
A pass move involves taking a section of the knot that involves only over-crossings (or only under-crossings), and then lifting that section above (or beneath respectively) the diagram and placing it back again in a different location. In particular, this routine searches for a different location that will involve fewer crossings than the original location.
This routine does not actually perform the pass move; it simply determines whether one exists.
The running time is cubic in the number of crossings.
true
if and only if there is a pass move that reduces the number of crossings.
|
inline |
Returns the HOMFLY polynomial of this link, as a polynomial in alpha and z.
This routine is simply an alias for homflyAZ(). See the documentation for homflyAZ() for further details.
To pretty-print this polynomial for human consumption, you can call Laurent2::str(Link::homflyVarX, Link::homflyVarY)
.
Bear in mind that each time the link changes, all of its polynomials will be deleted. Thus the reference that is returned from this routine should not be kept for later use. Instead, homfly() should be called again; this will be instantaneous if the HOMFLY polynomial has already been calculated.
alg | the algorithm with which to compute the polynomial. If you are not sure, the default (ALG_DEFAULT) is a safe choice. If you wish to specify a particular algorithm, there are currently two choices: ALG_BACKTRACK will use Kauffman's skein-template algorithm, and ALG_TREEWIDTH will use a fixed-parameter tractable treewidth-based algorithm. |
tracker | a progress tracker through which progress will be reported, or null if no progress reporting is required. |
const Laurent2< Integer > & regina::Link::homflyAZ | ( | Algorithm | alg = ALG_DEFAULT , |
ProgressTracker * | tracker = nullptr |
||
) | const |
Returns the HOMFLY polynomial of this link, as a polynomial in alpha and z.
This variant of the HOMFLY polynomial is described (amongst other places) in G. Gouesbet et al., "Computer evaluation of Homfly polynomials by using Gauss codes, with a skein-template algorithm", Applied Mathematics and Computation 105 (1999), 271-289.
The (alpha, z) and (l, m) variants of the HOMFLY polynomial are related by a simple transformation: alpha = l i and z = -m i, where i represents (as usual) a square root of -1.
This routine returns a Laurent polynomial in the two variables alpha and z (which are represented by x and y respectively in the class Laurent2).
If this is the empty link, then this routine will return the zero polynomial.
To pretty-print this polynomial for human consumption, you can call Laurent2::str(Link::homflyAZVarX, Link::homflyAZVarY)
.
The default implementation uses Kauffman's skein-template algorithm; see L. H. Kauffman, "State models for link polynomials", L'enseignement mathematique 36 (1990), 1-37, or for a more recent summary see G. Gouesbet et al., "Computer evaluation of Homfly polynomials by using Gauss codes, with a skein-template algorithm", Applied Mathematics and Computation 105 (1999), 271-289.
Bear in mind that each time the link changes, all of its polynomials will be deleted. Thus the reference that is returned from this routine should not be kept for later use. Instead, homflyAZ() should be called again; this will be instantaneous if the HOMFLY polynomial has already been calculated.
If the HOMFLY polynomial has already been computed (either in terms of alpha and z or in terms of l and m), 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 numbers of crossings.
Since Regina 7.0, this routine will not return until the polynomial 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.
alg | the algorithm with which to compute the polynomial. If you are not sure, the default (ALG_DEFAULT) is a safe choice. If you wish to specify a particular algorithm, there are currently two choices: ALG_BACKTRACK will use Kauffman's skein-template algorithm, and ALG_TREEWIDTH will use a fixed-parameter tractable treewidth-based algorithm. |
tracker | a progress tracker through which progress will be reported, or null if no progress reporting is required. |
Converts between the (alpha, z) and (l, m) representations of the HOMFLY polynomial.
The (alpha, z) and (l, m) variants are related by a simple transformation: alpha = l i and z = -m i, where i represents (as usual) a square root of -1.
See homflyAZ() and homflyLM() for further details.
homflyAZ | the HOMFLY polynomial of a link as a polynomial in alpha and z, where (alpha, z) are represented by (x, y) in the class Laurent2<Integer>. |
const Laurent2< Integer > & regina::Link::homflyLM | ( | Algorithm | alg = ALG_DEFAULT , |
ProgressTracker * | tracker = nullptr |
||
) | const |
Returns the HOMFLY polynomial of this link, as a polynomial in l and m.
This variant of the HOMFLY polynomial is described (amongst other places) in C. C. Adams, "The knot book", W. H. Freeman & Co., 1994.
The (alpha, z) and (l, m) variants of the HOMFLY polynomial are related by a simple transformation: alpha = l i and z = -m i, where i represents (as usual) a square root of -1.
This routine returns a Laurent polynomial in the two variables l and m (which are represented by x and y respectively in the class Laurent2).
If this is the empty link, then this routine will return the zero polynomial.
To pretty-print this polynomial for human consumption, you can call Laurent2::str(Link::homflyLMVarX, Link::homflyLMVarY)
.
The default implementation uses Kauffman's skein-template algorithm; see L. H. Kauffman, "State models for link polynomials", L'enseignement mathematique 36 (1990), 1-37, or for a more recent summary see G. Gouesbet et al., "Computer evaluation of Homfly polynomials by using Gauss codes, with a skein-template algorithm", Applied Mathematics and Computation 105 (1999), 271-289.
Bear in mind that each time the link changes, all of its polynomials will be deleted. Thus the reference that is returned from this routine should not be kept for later use. Instead, homflyLM() should be called again; this will be instantaneous if the HOMFLY polynomial has already been calculated.
If the HOMFLY polynomial has already been computed (either in terms of alpha and z or in terms of l and m), 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 numbers of crossings.
Since Regina 7.0, this routine will not return until the polynomial 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.
alg | the algorithm with which to compute the polynomial. If you are not sure, the default (ALG_DEFAULT) is a safe choice. If you wish to specify a particular algorithm, there are currently two choices: ALG_BACKTRACK will use Kauffman's skein-template algorithm, and ALG_TREEWIDTH will use a fixed-parameter tractable treewidth-based algorithm. |
tracker | a progress tracker through which progress will be reported, or null if no progress reporting is required. |
void regina::Link::insertTorusLink | ( | int | p, |
int | q, | ||
bool | positive = true |
||
) |
Inserts a new (p, q) torus link into this link.
The parameters p and q must be non-negative, but they do not need to be coprime.
All of the crossings in the new torus link component(s) will be positive if the argument positive is true
, or negative otherwise.
The new crossings and components will be inserted at the end of the respective lists in this link.
If your aim is to create a new torus link (as opposed to inserting one into an existing link), it is simpler to just call ExampleLink::torus().
p | the first parameter of the new torus link; this must be non-negative. |
q | the second parameter of the new torus link; this must also be non-negative. |
positive | true if the crossings in the new torus link should be positive, or false if they should be negative. |
bool regina::Link::intelligentSimplify | ( | ) |
Attempts to simplify the link diagram using fast and greedy heuristics.
Specifically, this routine tries combinations of Reidemeister moves with the aim of reducing the number of crossings.
Currently this routine uses simplifyToLocalMinimum() in combination with random type III Reidemeister moves.
Although intelligentSimplify() often works well, it can sometimes get stuck. If this link is a knot (i.e., it has precisely one component), then in such cases you can try the more powerful but (much) slower simplifyExhaustive() instead.
This routine will never reflect or reverse the link.
bool regina::Link::isAlternating | ( | ) | const |
Returns whether this knot diagram is alternating.
Note that this routine cannot tell whether the knot is alternating (i.e., whether there exists an alternating diagram). Instead, it simply returns whether this specific diagram is alternating or not.
The empty diagram and any zero-crossing unknot components will be considered alternating.
true
if this is an alternating diagram, or false
if this is a non-alternating diagram.
|
inline |
Determines whether this link is empty.
An empty link is one with no components at all.
true
if and only if this link is empty. std::string regina::Link::jenkins | ( | ) | const |
Exports this link using Bob Jenkins' text format, returning a single string.
Jenkins' format is lengthy. However, in contrast to classical Gauss codes or Dowker-Thistlethwaite notation, there are no topological ambiguities in the format, and reconstructing a link from Jenkins' format is simple. Moreover, the format is suitable for links with any number of components.
Jenkins' format is described in his HOMFLY polynomial software, which is available online from http://burtleburtle.net/bob/knot/homfly.html. The format consists of a sequence of integers separated by whitespace, constructed as follows:
As an example, you could describe the left-hand trefoil using the following sequence:
1 6 0 1 1 -1 2 1 0 -1 1 1 2 -1 0 -1 1 -1 2 -1
Another example is the Hopf link, which you could describe using the following sequence:
2 2 0 1 1 -1 2 0 -1 1 1 0 1 1 1
The string that is returned will contain multiple lines, and will end in a newline. The specific choice of whitespace (i.e., the "formatting" of the sequence) may change in future versions of Regina.
The routine jenkinsData() returns this same data in machine-readable format (as a C++ vector), instead of the human-readable format used here (a string). There is also another variant of jenkins() that writes directly to an output stream.
void regina::Link::jenkins | ( | std::ostream & | out | ) | const |
Exports this link to the given output stream using Bob Jenkins' text format.
See jenkins() for a full description of Jenkins' format as it is used in Regina.
The output from this routine is precisely the string that would be returned by jenkins(). In particular, the output will typically span multiple lines, and will finish with a newline.
See also jenkins(), which exports this link in Jenkins' format as a human-readable string, and jenkinsData(), which exports it as a machine-readable sequence of integers.
out | the output stream to which to write. |
std::vector< int > regina::Link::jenkinsData | ( | ) | const |
Exports this link using Bob Jenkins' text format, returning a vector of integers.
See jenkins() for a full description of Jenkins' format as it is used in Regina.
This routine returns machine-readable data (as a C++ vector); in contrast, jenkins() returns the same data in human-readable format (as a string).
const Laurent< Integer > & regina::Link::jones | ( | Algorithm | alg = ALG_DEFAULT , |
ProgressTracker * | tracker = nullptr |
||
) | const |
Returns the Jones polynomial of this link, but with all exponents doubled.
By "all exponents doubled", we are indicating that the Jones polynomial is in fact a Laurent polynomial in the square root of t. So, for example:
1/t + 1/t^3 - 1/t^4
, and so this routine returns the Laurent polynomial x^-2 + x^-6 - x^-8
.-1/sqrt(x) - 1/sqrt(x^5)
, and so this routine returns the Laurent polynomial -x^-1 - x^-5
.If this is the empty link, then this routine will return the zero polynomial.
Regina follows the conventions described in C. C. Adams, "The knot book", W. H. Freeman & Co., 1994. If you wish to convert to the conventions used by Khovanov as described in Dror Bar-Natan, "On Khovanov's categorifiction of the Jones polynomial", Algebraic & Geometric Topology 2 (2002), 337-370, you can simply take the polynomial returned by this routine and replace the variable x (which represents the square root of t) with the expression -q.
To pretty-print this polynomial for human consumption, you can call Laurent::str(Link::jonesVar)
.
Bear in mind that each time the link changes, all of its polynomials will be deleted. Thus the reference that is returned from this routine should not be kept for later use. Instead, jones() should be called again; this will be instantaneous if the Jones polynomial has already been calculated.
If this polynomial 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 numbers of crossings.
Since Regina 7.0, this routine will not return until the polynomial 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.
alg | the algorithm with which to compute the polynomial. If you are not sure, the default (ALG_DEFAULT) is a safe choice. If you wish to specify a particular algorithm, there are currently two choices: ALG_NAIVE is a slow algorithm that computes the Kauffman bracket by resolving all crossings in all possible ways, and ALG_TREEWIDTH uses a fixed-parameter tractable treewidth-based algorithm. |
tracker | a progress tracker through which progress will be reported, or null if no progress reporting is required. |
std::string regina::Link::knotSig | ( | bool | useReflection = true , |
bool | useReversal = true |
||
) | const |
Constructs the signature for this knot diagram.
A signature is a compact text representation of a knot diagram that unique determines the knot up to relabelling, rotation, and (optionally) reflection and/or reversal.
Currently signatures are only implemented for knots, not empty or multiple component links. If this link does not have precisely one component, then this routine will throw an exception. It is possible that in future versions of Regina, knot signatures will be expanded to cover all possible link diagrams (hence the choice of NotImplemented as the exception type).
The signature is constructed entirely of printable characters, and has length proportional to n log n
, where n is the number of crossings.
The routine fromKnotSig() can be used to recover a knot from its signature. The resulting knot might not be identical to the original, but it will be related by zero or more applications of relabelling, rotation, and/or (according to the arguments) reflection and reversal.
This routine runs in quadratic time.
NotImplemented | This link is empty or has multiple components. |
useReflection | true if the reflection of a knot diagram should have the same signature as the original, or false if these should be distinct (assuming the diagram is not symmetric under reflection). |
useReversal | true if the reversal of a knot diagram should have the same signature as the original, or false if these should be distinct (assuming the diagram is not symmetric under reversal). |
|
inline |
|
inline |
Is the HOMFLY polynomial of this link diagram already known? See homflyAZ() and homflyLM() for further details.
If this property is already known, future calls to homfly(), homflyAZ() and homflyLM() will all be very fast (simply returning the precalculated values).
true
if and only if this property is already known.
|
inline |
long regina::Link::linking | ( | ) | const |
Returns the linking number of this link.
This is an invariant of the link, computed as half the sum of the signs of all crossings that involve different link components.
The algorithm to compute linking number is linear time.
|
inline |
Returns a nice tree decomposition of the planar 4-valent multigraph formed by this link diagram.
This can (for example) be used in implementing algorithms that are fixed-parameter tractable in the treewidth of this 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 link has not been changed) then the same tree decomposition will be returned immediately.
If you wish to supply your own tree decomposition (as opposed to relying on the greedy heuristics that Regina implements), then you can supply it by calling useTreeDecomposition().
|
inline |
Determines if this link diagram is not combinatorially identical to the given link diagram.
Here "identical" means that:
other | the link diagram to compare with this. |
true
if and only if the two link diagrams are not combinatorially identical. Sets this to be a (deep) copy of the given link.
src | the link to copy. |
Moves the contents of the given link into this link.
This is a fast (constant time) operation.
All crossings that belong to src will be moved into this link, and so any Crossing pointers or StrandRef object will remain valid. Likewise, all cached properties will be moved into this link.
The link that is passed (src) will no longer be usable.
noexcept
, since it fires change events on this link 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).src | the link to move. |
bool regina::Link::operator== | ( | const Link & | other | ) | const |
Determines if this link diagram is combinatorially identical to the given link diagram.
Here "identical" means that:
other | the link diagram to compare with this. |
true
if and only if the two link diagrams are combinatorially identical. std::string regina::Link::orientedGauss | ( | ) | const |
Returns an oriented Gauss code for this knot, presented as a string.
The oriented Gauss code, based on a format used by Andreeva et al., is an extension of the classical Gauss code with additional characters to describe the orientation of the other strand passing by at each crossing. This extra information removes both the topological ambiguities and the complexity in the reconstruction procedure for classical Gauss codes.
This "oriented" format is described at http://www.javaview.de/services/knots/doc/description.html#gc, and it works as follows:
+<k
, -<k
, +>k
or ->k
, where:+
indicates that you are passing over the crossing labelled k, and the symbol -
indicates that you are passing under the crossing labelled k;<
indicates that the other strand of the crossing passes from right to left, and >
indicates that the other strand passes from left to right.As an example, you can represent the left-hand trefoil using the code:
+>1 -<2 +>3 -<1 +>2 -<3
Currently Regina only supports Gauss codes for knots, not empty or multiple component links. If this link does not have precisely one component, then this routine will throw an exception. It is possible that in future versions of Regina, Gauss codes will be expanded to cover all possible link diagrams (hence the choice of NotImplemented as the exception type).
This routine joins the tokens together as a single string. The tokens will be separated by single spaces, and there will be no newlines.
The routine orientedGaussData() returns this same data in machine-readable format (as a C++ vector of string tokens), instead of the human-readable format used here (a single long string). There is also another variant of orientedGauss() that writes directly to an output stream.
NotImplemented | This link is empty or has multiple components. |
void regina::Link::orientedGauss | ( | std::ostream & | out | ) | const |
Writes an oriented Gauss code for this knot to the given output stream.
See orientedGauss() for a full description of oriented Gauss codes as they are used in Regina, as well as their limitations.
The output from this routine is precisely the string that would be returned by orientedGauss(). In particular, the output does not contain any newlines.
See also orientedGauss(), which returns the oriented Gauss code as a human-readable string, and orientedGaussData(), which returns it as a machine-readable sequence of tokens.
NotImplemented | This link is empty or has multiple components. |
out | the output stream to which to write. |
std::vector< std::string > regina::Link::orientedGaussData | ( | ) | const |
Returns an oriented Gauss code for this knot, presented as a vector of string tokens.
See orientedGauss() for a full description of oriented Gauss codes as they are used in Regina, as well as their limitations.
For an n-crossing knot, the elements of the returned vector will be the 2n individual tokens of the form +<k
, -<k
, +>k
or ->k
that would normally be joined with whitespace to form a complete oriented Gauss code. For example, for the left-hand trefoil, the vector might contain the six tokens:
{ "+>1", "-<2", "+>3", "-<1", "+>2", "-<3" }
This routine returns machine-readable data (as a C++ vector); in contrast, orientedGauss() returns the same data in human-readable format (as a string).
NotImplemented | This link is empty or has multiple components. |
std::string regina::Link::pace | ( | ) | const |
Returns a text representation of the underlying planar 4-valent multigraph, using the PACE text format.
The text format is described in detail at https://pacechallenge.wordpress.com/pace-2016/track-a-treewidth/ , and is documented in detail by the routine writePACE().
This routine simply returns the output of writePACE() as a string, instead of writing it to an output stream.
See the writePACE() notes for further details.
|
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:
null
, since there is no "direct" PacketOf<Triangulation<3>>;The function inAnyPacket() is specific to Triangulation<3>, and is not offered for other Held types.
null
if this data is not (directly) held by a packet.
|
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.
null
if this data is not (directly) held by a packet. Link regina::Link::parallel | ( | int | k, |
Framing | framing = FRAMING_SEIFERT |
||
) | const |
Returns k cables of this link, all parallel to each other using the given framing.
This routine creates a new link by:
This link will not be modified.
k | the number of parallel copies to create. This must be non-negative. |
framing | the framing under which these copies will be parallel. |
std::string regina::Link::pd | ( | ) | const |
Returns a planar diagram code for this link, presented as a string.
Planar diagram codes encode the local information at each crossing, and present this information as a list of 4-tuples. These codes are available for links as well as knots, but they do come with some minor restrictions:
If you need a text code that can work with these types of link diagrams, you can always use Jenkins' format instead.
Regina adheres to a tight specification for the planar diagram codes that it outputs, in order to ensure compatibility with other software. In particular, Regina's codes are compatible with the Knot Atlas, as seen at http://katlas.org/wiki/Planar_Diagrams .
In detail: a planar diagram code for an n-crossing link is formed from a sequence of n 4-tuples of integers. Regina constructs this sequence as follows:
An example, you can represent the right-hand trefoil using the code:
[[1, 5, 2, 4], [3, 1, 4, 6], [5, 3, 6, 2]]
Some points to be aware of:
This routine formats the list of 4-tuples as a string, in a way that is consistent with the description in the Knot Atlas at http://katlas.org/wiki/Planar_Diagrams .
In particular, each 4-tuple will be formatted with square brackets, commas, and the prefix X
, and the main list will be formatted with square brackets, commas, and the prefix PD
. An example (for the right-handed trefoil) is:
PD[X[1, 5, 2, 4], X[3, 1, 4, 6], X[5, 3, 6, 2]]
The routine pdData() returns this same data in machine-readable format (as a C++ vector of 4-tuples of integers), instead of the human-readable format used here (a single string). There is also another variant of pd() that writes directly to an output stream.
void regina::Link::pd | ( | std::ostream & | out | ) | const |
Writes a planar diagram code for this link to the given output stream.
See pd() for a full description of planar diagram codes as they are used in Regina, as well as their limitations.
The output from this routine is precisely the string that would be returned by pd(). In particular, the output does not contain any newlines.
See also pd(), which returns the planar diagram code as a human-readable string, and pdData(), which returns it as a machine-readable sequence of 4-tuples of integers.
out | the output stream to which to write. |
std::vector< std::array< int, 4 > > regina::Link::pdData | ( | ) | const |
Returns a planar diagram code for this link, presented as vector of 4-tuples.
See pd() for a full description of planar diagram codes as they are used in Regina, as well as their limitations.
This routine returns machine-readable data (as a C++ vector); in contrast, pd() returns the same data in human-readable format (as a string).
bool regina::Link::r1 | ( | Crossing * | crossing, |
bool | check = true , |
||
bool | perform = true |
||
) |
Tests for and/or performs a type I Reidemeister move to remove a crossing.
There are two boolean arguments that control the behaviour of this routine: check and perform.
true
(the default), then this routine will first check whether this move can be performed at the given location. If so, it will perform the move and return true
. If not, it will do nothing and return false
.true
but perform is false
, then this routine will simply check whether this move can be performed at the given location and return true
or false
accordingly.false
but perform is true
, then this routine will perform the move without any prior checks, and will always return true
. In this case, it must be known in advance that the move can be performed at the given location.false
, then this routine does nothing and just returns true
. (There is no reason to use this combination of arguments.)The location of this move is specified by the argument crossing, which indicates the crossing that will be removed. Specifically, this move involves undoing a trivial twist at the given crossing.
You may pass a null pointer for crossing. However, in this case the move cannot be performed, which means (i) check must be true
, and therefore (ii) this routine will do nothing and return false
.
true
but check is false
, then it must be known in advance that this move can be performed at the given location. crossing | identifies the crossing to be removed. |
check | true if we are to check whether the move can be performed at the given location. |
perform | true if we should actually perform the move. |
true
, this function returns true
if and only if the move can be performed. If check is false
, this function always returns true
. bool regina::Link::r1 | ( | StrandRef | arc, |
int | side, | ||
int | sign, | ||
bool | check = true , |
||
bool | perform = true |
||
) |
Tests for and/or performs a type I Reidemeister move to add a new crossing.
There are two boolean arguments that control the behaviour of this routine: check and perform.
true
(the default), then this routine will first check whether this move can be performed at the given location. If so, it will perform the move and return true
. If not, it will do nothing and return false
.true
but perform is false
, then this routine will simply check whether this move can be performed at the given location and return true
or false
accordingly.false
but perform is true
, then this routine will perform the move without any prior checks, and will always return true
. In this case, it must be known in advance that the move can be performed at the given location.false
, then this routine does nothing and just returns true
. (There is no reason to use this combination of arguments.)The location of this move is specified by the argument arc. Specifically, this move involves adding a trivial twist to the given arc; the arguments side and sign indicate on which side of the arc and with which orientation the new twist will be made. See the StrandRef documentation for the convention on how arcs are represented using StrandRef objects.
If arc is a null reference, then the new twist will be added to a zero-crossing unknot component; it will be assumed that this unknot component is oriented clockwise. If arc is null but there is no zero-crossing component then the move cannot be performed, and if arc is null but there are multiple zero-crossing components then the first such component will be used.
This move is almost always able to be performed: the only situation in which it cannot be performed is if arc is a null reference but this link contains no zero-crossing components, as discussed above.
The existing crossings in this link will keep the same indices, and the new crossing will be given the next index that is available.
true
but check is false
, then it must be known in advance that this move can be performed at the given location. arc | identifies the arc of the link in which the new twist will be introduced, as described above. |
side | 0 if the twist should be introduced on the left of the arc (when walking along the arc in the forward direction), or 1 if the twist should be introduced on the right of the arc. |
sign | the sign of the new crossing that will be introduced as part of the twist; this must be +1 or -1. |
check | true if we are to check whether the move can be performed at the given location. |
perform | true if we should actually perform the move. |
true
, this function returns true
if and only if the move can be performed. If check is false
, this function always returns true
.
|
inline |
Tests for and/or performs a type II Reidemeister move to remove two crossings.
There are two variants of this routine: one that takes an arc, and one that takes a crossing. The other variant, which takes an arc, is more flexible (since either of the two arcs involved in this move can be passed). This variant, which takes a crossing, offers a canonical way of performing the move (since for each move there is exactly one crossing that describes it).
There are two boolean arguments that control the behaviour of this routine: check and perform.
true
(the default), then this routine will first check whether this move can be performed at the given location. If so, it will perform the move and return true
. If not, it will do nothing and return false
.true
but perform is false
, then this routine will simply check whether this move can be performed at the given location and return true
or false
accordingly.false
but perform is true
, then this routine will perform the move without any prior checks, and will always return true
. In this case, it must be known in advance that the move can be performed at the given location.false
, then this routine does nothing and just returns true
. (There is no reason to use this combination of arguments.)The location of this move is specified by the argument crossing, Specifically, this move involves pulling apart two arcs of the link (one upper, one lower) that both run between the same pair of crossings. The given crossing should be the start point of the upper arc; that is, when following the upper arc forwards, crossing should be the first of the two crossings that we encounter. Note that crossing is one of the two crossings that will be removed by this move.
You may pass a null pointer for crossing. However, in this case the move cannot be performed, which means (i) check must be true
, and therefore (ii) this routine will do nothing and return false
.
true
but check is false
, then it must be known in advance that this move can be performed at the given location. crossing | identifies the crossing at the beginning of the "upper" arc that features in this move, as described above. |
check | true if we are to check whether the move is legal. |
perform | true if we should actually perform the move. |
true
, this function returns true
if and only if the requested move is legal. If check is false
, this function always returns true
. bool regina::Link::r2 | ( | StrandRef | arc, |
bool | check = true , |
||
bool | perform = true |
||
) |
Tests for and/or performs a type II Reidemeister move to remove two crossings.
There are two variants of this routine: one that takes an arc, and one that takes a crossing. This variant, which takes an arc, is more flexible (since either of the two arcs involved in this move can be passed). The other variant, which takes a crossing, offers a canonical way of performing the move (since for each move there is exactly one crossing that describes it).
There are two boolean arguments that control the behaviour of this routine: check and perform.
true
(the default), then this routine will first check whether this move can be performed at the given location. If so, it will perform the move and return true
. If not, it will do nothing and return false
.true
but perform is false
, then this routine will simply check whether this move can be performed at the given location and return true
or false
accordingly.false
but perform is true
, then this routine will perform the move without any prior checks, and will always return true
. In this case, it must be known in advance that the move can be performed at the given location.false
, then this routine does nothing and just returns true
. (There is no reason to use this combination of arguments.)The location of this move is specified by the argument arc. Specifically, this move involves pulling apart two arcs of the link that surround a bigon; the given arc must be one of these two arcs. See the StrandRef documentation for the convention on how arcs are represented using StrandRef objects.
You may pass a null reference for arc. However, in this case the move cannot be performed, which means (i) check must be true
, and therefore (ii) this routine will do nothing and return false
.
true
but check is false
, then it must be known in advance that this move can be performed at the given location. arc | identifies one of the arcs of the bigon about which the move will be performed, as described above. |
check | true if we are to check whether the move is legal. |
perform | true if we should actually perform the move. |
true
, this function returns true
if and only if the requested move is legal. If check is false
, this function always returns true
. bool regina::Link::r2 | ( | StrandRef | upperArc, |
int | upperSide, | ||
StrandRef | lowerArc, | ||
int | lowerSide, | ||
bool | check = true , |
||
bool | perform = true |
||
) |
Tests for and/or performs a type II Reidemeister move to add two new crossings.
There are two boolean arguments that control the behaviour of this routine: check and perform.
true
(the default), then this routine will first check whether this move can be performed at the given location. If so, it will perform the move and return true
. If not, it will do nothing and return false
.true
but perform is false
, then this routine will simply check whether this move can be performed at the given location and return true
or false
accordingly.false
but perform is true
, then this routine will perform the move without any prior checks, and will always return true
. In this case, it must be known in advance that the move can be performed at the given location.false
, then this routine does nothing and just returns true
. (There is no reason to use this combination of arguments.)The location of this move is specified by the arguments upperArc, upperSide, lowerArc and lowerSide. Specifically, this move involves taking the arc upperArc and pushing it over lowerArc so that the two arcs overlap. The arguments upperSide and lowerSide indicate on which side of each arc the overlap takes place. See the StrandRef documentation for the convention on how arcs are represented using StrandRef objects.
If either upperArc or lowerArc is a null reference, then the move will be performed upon a zero-crossing unknot component; it will be assumed that this unknot component is oriented clockwise. If one of these arguments is a null reference but there is no zero-crossing component then the move cannot be performed, and if there are multiple zero-crossing components then the first such component will be used.
Likewise, if both arcs are null references, then the move will be performed upon two different zero-crossing unknot components. In this case, if there are fewer than two such components then the move cannot be performed, and otherwise upperArc will be the first such component and lowerArc will be the second.
Currently, Regina cannot perform the move when upperArc and lowerArc represent the same arc (or the same zero-crossing unknot component). In this case there is a workaround: you can achieve the same effect by performing two type I Reidemeister moves (i.e., by adding two twists).
The existing crossings in this link will keep the same indices, and the two new crossings will be given the next two indices that are available.
true
but check is false
, then it must be known in advance that this move can be performed at the given location. upperArc | identifies the arc of the link which will be passed over the other, as described above. |
upperSide | 0 if the new overlap should take place on the left of upperArc (when walking along upperArc in the forward direction), or 1 if the new overlap should take place on the right of upperArc. |
lowerArc | identifies the arc of the link which will be passed beneath the other, as described above. |
lowerSide | 0 if the new overlap should take place on the left of lowerArc (when walking along lowerArc in the forward direction), or 1 if the new overlap should take place on the right of lowerArc. |
check | true if we are to check whether the move can be performed at the given location. |
perform | true if we should actually perform the move. |
true
, this function returns true
if and only if the move can be performed. If check is false
, this function always returns true
.
|
inline |
Tests for and/or performs a type III Reidemeister move.
There are two variants of this routine: one that takes an arc, and one that takes a crossing. The other variant, which takes an arc, is more flexible (since any of the three arcs involved in this move can be passed). This variant, which takes a crossing, offers a canonical way of performing the move (since for each move there is exactly one crossing that describes it).
There are two boolean arguments that control the behaviour of this routine: check and perform.
true
(the default), then this routine will first check whether this move can be performed at the given location. If so, it will perform the move and return true
. If not, it will do nothing and return false
.true
but perform is false
, then this routine will simply check whether this move can be performed at the given location and return true
or false
accordingly.false
but perform is true
, then this routine will perform the move without any prior checks, and will always return true
. In this case, it must be known in advance that the move can be performed at the given location.false
, then this routine does nothing and just returns true
. (There is no reason to use this combination of arguments.)The location of this move is specified by the arguments crossing and side. Specifically, this move takes place around a triangle, and one of the arcs of this triangle is uppermost (in that it passes above the other two arcs). The given crossing should be the start point of this uppermost arc; that is, when following the arc forwards, crossing should be the first of the two crossings that we encounter. The additional argument side indicates on which side of the uppermost arc the third crossing is located.
You may pass a null pointer for crossing. However, in this case the move cannot be performed, which means (i) check must be true
, and therefore (ii) this routine will do nothing and return false
.
All crossings in this link will keep the same indices, and no crossings will be created or destroyed. Instead, the three crossings involved in this move will simply be reordered along the various segments of the link.
true
but check is false
, then it must be known in advance that this move can be performed at the given location. crossing | identifies the crossing at the beginning of the "uppermost" arc that features in this move, as described above. |
side | 0 if the third crossing of the triangle is located to the left of the uppermost arc (when walking along the arc in the forward direction), or 1 if the third crossing is located on the right of the uppermost arc. |
check | true if we are to check whether the move can be performed at the given location. |
perform | true if we should actually perform the move. |
true
, this function returns true
if and only if the move can be performed. If check is false
, this function always returns true
. bool regina::Link::r3 | ( | StrandRef | arc, |
int | side, | ||
bool | check = true , |
||
bool | perform = true |
||
) |
Tests for and/or performs a type III Reidemeister move.
There are two variants of this routine: one that takes an arc, and one that takes a crossing. This variant, which takes an arc, is more flexible (since any of the three arcs involved in this move can be passed). The other variant, which takes a crossing, offers a canonical way of performing the move (since for each move there is exactly one crossing that describes it).
There are two boolean arguments that control the behaviour of this routine: check and perform.
true
(the default), then this routine will first check whether this move can be performed at the given location. If so, it will perform the move and return true
. If not, it will do nothing and return false
.true
but perform is false
, then this routine will simply check whether this move can be performed at the given location and return true
or false
accordingly.false
but perform is true
, then this routine will perform the move without any prior checks, and will always return true
. In this case, it must be known in advance that the move can be performed at the given location.false
, then this routine does nothing and just returns true
. (There is no reason to use this combination of arguments.)The location of this move is specified by the arguments arc and side. Specifically, this move takes place around a triangle; the given arc must form one of the three edges of this triangle. The argument side indicates on which side of the arc the third crossing is located. See the StrandRef documentation for the convention on how arcs are represented using StrandRef objects.
You may pass a null reference for arc. However, in this case the move cannot be performed, which means (i) check must be true
, and therefore (ii) this routine will do nothing and return false
.
All crossings in this link will keep the same indices, and no crossings will be created or destroyed. Instead, the three crossings involved in this move will simply be reordered along the various segments of the link.
true
but check is false
, then it must be known in advance that this move can be performed at the given location. arc | identifies one of the arcs of the triangle about which the move will be performed, as described above. |
side | 0 if the third crossing of the triangle is located to the left of the arc (when walking along the arc in the forward direction), or 1 if the third crossing is located on the right of the arc. |
check | true if we are to check whether the move can be performed at the given location. |
perform | true if we should actually perform the move. |
true
, this function returns true
if and only if the move can be performed. If check is false
, this function always returns true
. void regina::Link::reflect | ( | ) |
Converts this link into its reflection.
This routine changes the sign of every crossing, but leaves the upper and lower strands the same. This operation corresponds to reflecting the link diagram about some axis in the plane.
void regina::Link::resolve | ( | Crossing * | c | ) |
Resolves the given crossing.
The two incoming strands will switch connections with the two outgoing strands, with the result that the given crossing is removed entirely.
c | the crossing to resolve. |
void regina::Link::reverse | ( | ) |
Reverses the orientation of every component of this link.
This routine preserves both the sign and the upper/lower positions at every crossing, but switches all incoming strands with outgoing strands and vice versa (so next() becomes prev(), and prev() becomes next()).
|
inline |
Explores all knot diagrams that can be reached from this via Reidemeister moves, without exceeding a given number of additional crossings.
This routine is only available for knots at the present time. If this link has multiple (or zero) components, then this routine will throw an exception (as described below).
This routine iterates through all knot diagrams that can be reached from this via Reidemeister moves, without ever exceeding height additional crossings beyond the original number. With the current implementation, these diagrams could become reflected and/or reversed, and moreover each diagram will only be considered once up to reflection and/or reversal; be aware that this behaviour could change and/or become configurable in a future version of Regina.
For every such knot diagram (including this starting diagram), this routine will call action (which must be a function or some other callable object).
true
, then this indicates that processing should stop immediately (i.e., no more knot diagrams will be processed).This routine can be very slow and very memory-intensive, since the number of knot diagrams it visits may be exponential in the number of crossings, and it records every knot diagram that it visits (so as to avoid revisiting the same diagram 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 crossings. This means that the routine will never terminate, unless action returns true
for some knot diagram that is passed to it.
Since Regina 7.0, this routine will not return until the exploration of knot diagrams 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 nThreads. 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).
FailedPrecondition | this link is empty or has more than one component. If a progress tracker was passed, it will be marked as finished before the exception is thrown. |
height | the maximum number of additional crossings to allow beyond the number of crossings originally present in this knot diagram, or a negative number if this should not be bounded. |
nThreads | the number of threads to use. If this is 1 or smaller then the routine will run single-threaded. |
tracker | a progress tracker through which progress will be reported, or null if no progress reporting is required. |
action | a function (or other callable object) to call for each knot diagram that is found. |
args | any additional arguments that should be passed to action, following the initial knot argument(s). |
true
if some call to action returned true
(thereby terminating the search early), or false
if the search ran to completion. void regina::Link::rotate | ( | ) |
Rotates this link diagram, converting it into a different diagram of the same link.
This routine keeps the sign of each crossing fixed, but switches the upper and lower strands. This operation corresponds to a 3-dimensional rotation about some axis in the plane.
void regina::Link::selfFrame | ( | ) |
Adds trivial twists to this link to ensure that each component has zero writhe.
Here the writhe of a component c is the sum of the signs of all crossings at which c crosses itself.
Any component(s) that already have zero writhe will be left unchanged.
This link will be modified directly.
|
inline |
Attempts to simplify this knot diagram using a slow but exhaustive search through the Reidemeister graph.
This routine is more powerful but much slower than intelligentSimplify().
Unlike intelligentSimplify(), this routine could potentially reflect or reverse the link.
This routine is only available for knots at the present time. If this link has multiple (or zero) components, then this routine will throw an exception (as described below).
This routine will iterate through all knot diagrams that can be reached from this via Reidemeister moves, without ever exceeding height additional crossings beyond the original number.
If at any stage it finds a diagram with fewer crossings than the original, then this routine will call intelligentSimplify() to simplify the diagram further if possible and will then return true
. If it cannot find a diagram with fewer crossings then it will leave this knot diagram unchanged and return false
.
This routine can be very slow and very memory-intensive: the number of knot diagrams it visits may be exponential in the number of crossings, and it records every diagram that it visits (so as to avoid revisiting the same diagram 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 crossings. This means that the routine will not terminate until a simpler diagram is found. If no simpler diagram exists then the only way to terminate this function is to cancel the operation via a progress tracker (read on for details).
If you want a fast simplification routine, you should call intelligentSimplify() instead. The benefit of simplifyExhaustive() is that, for very stubborn knot diagrams where intelligentSimplify() 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 knot diagram 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 nThreads. Even in multithreaded mode, this routine will not return until processing has finished (i.e., either the diagram was simplified or the search was exhausted).
If this routine is unable to simplify the knot diagram, then this knot diagram will not be changed.
FailedPrecondition | this link has more than one component. If a progress tracker was passed, it will be marked as finished before the exception is thrown. |
height | the maximum number of additional crossings to allow beyond the number of crossings originally present in this diagram, or a negative number if this should not be bounded. |
nThreads | the number of threads to use. If this is 1 or smaller then the routine will run single-threaded. |
tracker | a progress tracker through which progress will be reported, or null if no progress reporting is required. |
true
if and only if this diagram was successfully simplified to fewer crossings. bool regina::Link::simplifyToLocalMinimum | ( | bool | perform = true | ) |
Uses type I and II Reidemeister moves to reduce the link monotonically to some local minimum number of crossings.
End users will probably not want to call this routine. You should call intelligentSimplify() if you want a fast (and usually effective) means of simplifying a link. If this link is a knot (i.e., it has precisely one component), then you can also call simplifyExhaustive() if you are still stuck and you want to try a slower but more powerful method instead.
Type III Reidemeister moves (which do not reduce the number of crossings) are not used in this routine. Such moves do however feature in intelligentSimplify().
This routine will never reflect or reverse the link.
perform | true if we are to perform the simplifications, or false if we are only to investigate whether simplifications are possible (defaults to true ). |
true
, this routine returns true
if and only if the link was changed to reduce the number of crossings; if perform is false
, this routine returns true
if and only if it determines that it is capable of performing such a change.
|
inline |
Returns the number of crossings in this link.
Note that a link can have more components than crossings (since it may contain additional zero-crossing unknot components).
|
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.
str()
will use precisely this function, and for most classes the Python repr()
function will incorporate this into its output.
|
inline |
Returns the strand in the link with the given integer ID.
Each strand ID is of the form 2c+s, where c is the index of the crossing, and s is 0 or 1 for the lower or upper strand respectively. A null strand reference (as used to indicate 0-crossing unknot components) has an ID of -1.
id | an integer between -1 and 2*size()-1 inclusive. |
void regina::Link::swap | ( | Link & | other | ) |
Swaps the contents of this and the given link.
All crossings that belong to this link will be moved to other, and all crossings that belong to other will be moved to this link. Likewise, all cached properties (e.g., tree decompositions) will be swapped.
In particular, any Crossing pointers or references and any StrandRef objects will remain valid.
This routine will behave correctly if other is in fact this link.
noexcept
, since it fires change events on both links which may in turn call arbitrary code via any registered packet listeners.other | the link whose contents should be swapped with this. |
|
inline |
Deprecated routine that swaps the contents of this and the given link.
other | the link whose contents should be swapped with this. |
Translates a strand reference for some other link into the corresponding strand reference for this link.
Specifically: if other refers to some strand (upper or lower) of crossing number k of some other link, then the return value will refer to the same strand (upper or lower) of crossing number k of this link.
This routine behaves correctly even if other is a null reference.
other | the strand reference to translate. |
|
inline |
Instructs Regina to use the given tree decomposition as the starting point whenever it needs a tree decomposition for this link.
For some link routines, including niceTreeDecomposition() as well as computations such as jones() that support the option ALG_TREEWIDTH, Regina needs a tree decomposition of the planar 4-valent multigraph formed by this link diagram.
By default, Regina will compute (and then cache) such a tree decomposition itself, using in-built greedy heuristics. This routine allows you to supply your own tree decomposition (which, for example, might be a smaller-width tree decomposition that you found using third-party software). By supplying your own tree decomposition td through this routine, Regina will throw away any pre-computed tree decomposition that it has cached, and will instead cache td for future use instead.
Regina may modify the given tree decomposition for its purposes. In particular, td does not need to be a nice tree decomposition (indeed, it does not need to have any special properties beyond the definition of a tree decomposition). Regina will automatically create a nice tree decomposition from it if td is not nice already.
td | a tree decomposition of the planar 4-valent multigraph formed by this link diagram. |
|
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.
void regina::Link::writePACE | ( | std::ostream & | out | ) | const |
Outputs the underlying planar 4-valent multigraph using the PACE text format.
The text format is described in detail at https://pacechallenge.wordpress.com/pace-2016/track-a-treewidth/ .
In summary, the output will consist of several lines of text:
p tw num_vertices num_edges
. Note that, since the underlying graph comes from a link diagram, we will always have num_edges equal to twice num_vertices.u v
, indicating an edge from vertex number u to vertex number v. In this format, vertices are numbered 1,2,...,num_vertices.An example of this text format is as follows:
p tw 4 8 1 2 1 4 1 2 2 3 3 4 1 3 3 4 2 4
out | the output stream to which to write. |
void regina::Link::writeTextLong | ( | std::ostream & | out | ) | const |
Writes a detailed text representation of this link to the given output stream.
out | the output stream to which to write. |
void regina::Link::writeTextShort | ( | std::ostream & | out | ) | const |
Writes a short text representation of this link to the given output stream.
out | the output stream to which to write. |
|
inline |
Returns the writhe of this link diagram.
This is not an invariant of the link; instead it depends on the particular link diagram. It is computed as the sum of the signs of all crossings. It is preserved under Reidemeister moves II and III, but not I.
|
inline |
Returns the writhe of a single component of this link diagram.
This is the writhe of the diagram when all other components are removed. It is computed as the sum of the signs of all crossings at which the given component crosses itself.
In this version of writheOfComponent(), the component is indicated by its index. This function is equivalent to calling writheOfComponent(component(index))
.
index | the index of the requested component. This must be between 0 and countComponents()-1 inclusive. |
long regina::Link::writheOfComponent | ( | StrandRef | component | ) | const |
Returns the writhe of a single component of this link diagram.
This is the writhe of the diagram when all other components are removed. It is computed as the sum of the signs of all crossings at which the given component crosses itself.
In this version of writheOfComponent(), the component is indicated by the argument strand, which may be any strand along the component. In particular, strand does not need to be the "starting strand" returned by component().
The given strand may be a null strand, in which case the return value will be 0 (since Regina uses null strands to refer to zero-crossing unknot components). This is always allowed, regardless of whether the link actually contains any zero-crossing unknot components.
component | any strand along the component of interest. |
|
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.
|
staticconstexpr |
The name of the first variable used in the variant of the HOMFLY polynomial as returned by homflyAZ().
This is provided to help with pretty-printing HOMFLY polynomials for human consumption.
Since homflyAZ() returns a Laurent polynomial in alpha and z, this string just contains the mathematical symbol alpha (encoded in UTF-8).
To pretty-print this HOMFLY polynomial for human consumption, you can call Laurent2::str(Link::homflyAZVarX, Link::homflyAZVarY)
.
|
staticconstexpr |
The name of the second variable used in the variant of the HOMFLY polynomial as returned by homflyAZ().
This is provided to help with pretty-printing HOMFLY polynomials for human consumption.
Since homflyAZ() returns a Laurent polynomial in alpha and z, this string just contains the single character z.
To pretty-print this HOMFLY polynomial for human consumption, you can call Laurent2::str(Link::homflyAZVarX, Link::homflyAZVarY)
.
|
staticconstexpr |
The name of the first variable used in the variant of the HOMFLY polynomial as returned by homflyLM().
This is provided to help with pretty-printing HOMFLY polynomials for human consumption.
Since homflyLM() returns a Laurent polynomial in l and m, this string just contains the mathematical script symbol for l (encoded in UTF-8).
To pretty-print this HOMFLY polynomial for human consumption, you can call Laurent2::str(Link::homflyLMVarX, Link::homflyLMVarY)
.
|
staticconstexpr |
The name of the second variable used in the variant of the HOMFLY polynomial as returned by homflyLM().
This is provided to help with pretty-printing HOMFLY polynomials for human consumption.
Since homflyLM() returns a Laurent polynomial in l and m, this string just contains the single character m.
To pretty-print this HOMFLY polynomial for human consumption, you can call Laurent2::str(Link::homflyLMVarX, Link::homflyLMVarY)
.
|
staticconstexpr |
The name of the first variable used in the variant of the HOMFLY polynomial as returned by homfly().
This is simply an alias for homflyAZVarX. See the documentation for homflyAZVarX for further details.
|
staticconstexpr |
The name of the second variable used in the variant of the HOMFLY polynomial as returned by homfly().
This is simply an alias for homflyAZVarY. See the documentation for homflyAZVarY for further details.
|
staticconstexpr |
The name of the variable used in the Jones polynomial, as returned by jones().
This is provided to help with pretty-printing Jones polynomials for human consumption.
Since jones() returns a Laurent polynomial in the square root of t, this string is just a human-readable representation of the square root of t (encoded in UTF-8).
To pretty-print the Jones polynomial for human consumption, you can call Laurent::str(Link::jonesVar)
.