Regina 7.4 Calculation Engine
regina::Arrow Class Reference

Represents a multivariate polynomial of the type used by arrow polynomials of links. More...

#include <maths/arrow.h>

Inheritance diagram for regina::Arrow:
regina::ShortOutput< Arrow, true > regina::TightEncodable< Arrow > regina::Output< Arrow, supportsUtf8 >

Public Types

using Coefficient = Integer
 The type of each coefficient of the polynomial.
 
using DiagramSequence = LightweightSequence<size_t>
 The type used to represent a product of diagram variables.
 

Public Member Functions

 Arrow ()=default
 Creates the zero polynomial.
 
 Arrow (const Arrow &)=default
 Creates a new copy of the given polynomial.
 
 Arrow (Arrow &&) noexcept=default
 Moves the contents of the given polynomial to this new polynomial.
 
template<typename iterator , typename deref = decltype(*iterator())>
 Arrow (iterator begin, iterator end)
 Creates a new polynomial from the given collection of diagram sequences and non-zero Laurent polynomials in A.
 
 Arrow (std::initializer_list< std::pair< DiagramSequence, Laurent< Integer > > > pairs)
 Creates a new polynomial from a hard-coded collection of diagram sequences and non-zero Laurent polynomials in A.
 
 Arrow (Laurent< Integer > laurent)
 Creates the given Laurent polynomial in A.
 
void init ()
 Sets this to become the zero polynomial.
 
void initDiagram (const DiagramSequence &d)
 Sets this to become the given product of diagram variables, using a deep copy.
 
void initDiagram (DiagramSequence &&d)
 Sets this to become the given product of diagram variables, using a fast move operation.
 
bool isZero () const
 Returns whether this is the zero polynomial.
 
const Laurent< Integer > & operator[] (const DiagramSequence &d) const
 Returns the Laurent polynomial in A that is attached to the given product of diagram variables.
 
void set (const DiagramSequence &d, const Laurent< Integer > &value)
 Changes the Laurent polynomial in A that is attached to the given product of diagram variables.
 
void set (const DiagramSequence &d, Laurent< Integer > &&value)
 Changes the Laurent polynomial in A that is attached to the given product of diagram variables.
 
bool operator== (const Arrow &rhs) const
 Tests whether this and the given polynomial are equal.
 
bool operator== (const Laurent< Integer > &rhs) const
 Tests whether this is equal to the given Laurent polynomial in A.
 
std::strong_ordering operator<=> (const Arrow &rhs) const
 Compares this against the given polynomial under a total ordering of all arrow polynomials.
 
Arrowoperator= (const Arrow &)=default
 Sets this to be a copy of the given polynomial.
 
Arrowoperator= (Arrow &&value) noexcept=default
 Moves the contents of the given polynomial to this polynomial.
 
Arrowoperator= (Laurent< Integer > laurent)
 Sets this to be the given Laurent polynomial in A.
 
void swap (Arrow &other) noexcept
 Swaps the contents of this and the given polynomial.
 
void shift (long s)
 Multiplies this polynomial by A^s for some integer s.
 
void scaleUp (long k)
 Multiplies all exponents of A in this polynomial by k for some integer k.
 
void scaleDown (long k)
 Divides all exponents in this polynomial by k for some integer k.
 
void negate ()
 Negates this polynomial.
 
void invertA ()
 Replaces A with A^-1 in this polynomial.
 
void multDiagram (size_t index)
 Multiplies this polynomial by the given diagram variable.
 
Laurent< IntegersumLaurent () const
 Returns the sum of all Laurent polynomials in A that are attached to each diagram sequence.
 
Arrowoperator*= (const Integer &scalar)
 Multiplies this polynomial by the given integer constant.
 
Arrowoperator*= (const Laurent< Integer > &laurent)
 Multiplies this arrow polynomial by the given Laurent polynomial in A.
 
Arrowoperator+= (const Arrow &other)
 Adds the given polynomial to this.
 
Arrowoperator-= (const Arrow &other)
 Subtracts the given polynomial from this.
 
Arrowoperator*= (const Arrow &other)
 Multiplies this by the given polynomial.
 
void writeTextShort (std::ostream &out, bool utf8=false) const
 Writes this polynomial to the given output stream.
 
void tightEncode (std::ostream &out) const
 Writes the tight encoding of this polynomial to the given output stream.
 
void writeTextLong (std::ostream &out) const
 A default implementation for detailed output.
 
std::string str () const
 Returns a short text representation of this object.
 
std::string utf8 () const
 Returns a short text representation of this object using unicode characters.
 
std::string detail () const
 Returns a detailed text representation of this object.
 
std::string tightEncoding () const
 Returns the tight encoding of this object.
 
size_t hash () const
 Hashes this object to a non-negative integer, allowing it to be used for keys in hash tables.
 

Static Public Member Functions

static Arrow tightDecode (std::istream &input)
 Reconstructs a polynomial from its given tight encoding.
 
static Arrow tightDecoding (const std::string &enc)
 Reconstructs an object of type T from its given tight encoding.
 

Friends

Arrow operator* (const Arrow &lhs, const Arrow &rhs)
 Multiplies the two given polynomials.
 

Detailed Description

Represents a multivariate polynomial of the type used by arrow polynomials of links.

An arrow polynomial is a polynomial in the "ordinary variable" A and a finite number of "diagram variables" K_1,K_2,.... The ordinary variable may appear with any integer exponents, including negative exponents (as in a Laurent polynomial). The diagram variables may only appear with non-negative integer exponents (as in an ordinary polynomial). All of the variables commute, and all of the coefficients are integers.

This class is implemented as a collection of Laurent polynomials in A, each attached to a different product of diagram variables (K_1)^(a_1) (K_2)^(a_2) .... We represent each such product of diagram variables by the sequence of non-negative integers a_1,a_2,..., where the final integer is strictly positive; for the trivial product with no diagram variables at all we use the empty sequence. In the notes below we call such a sequence a diagram sequence.

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

Member Typedef Documentation

◆ Coefficient

The type of each coefficient of the polynomial.

◆ DiagramSequence

The type used to represent a product of diagram variables.

Constructor & Destructor Documentation

◆ Arrow() [1/6]

regina::Arrow::Arrow ( )
default

Creates the zero polynomial.

◆ Arrow() [2/6]

regina::Arrow::Arrow ( const Arrow & )
default

Creates a new copy of the given polynomial.

This constructor induces a deep copy of the given polynomial.

◆ Arrow() [3/6]

regina::Arrow::Arrow ( Arrow && )
defaultnoexcept

Moves the contents of the given polynomial to this new polynomial.

This is a fast (constant time) operation.

The polynomial that was passed will no longer be usable.

◆ Arrow() [4/6]

template<typename iterator , typename deref >
regina::Arrow::Arrow ( iterator begin,
iterator end )
inline

Creates a new polynomial from the given collection of diagram sequences and non-zero Laurent polynomials in A.

The data should be presented as a collection of pairs of the form (seq, laurent), where seq is a diagram sequence and laurent is the associated Laurent polynomial in A.

The pairs may be given in any order. An empty sequence will be treated as the zero polynomial.

Unlike the std::initializer_list constructor, zero Laurent polynomials are allowed (these will be silently ignored), and multiple pairs with the same diagram sequences are also allowed (these will be summed together).

This routine is targeted more towards Python users (since in C++ it is often easier to hard-code arrow polynomials using the std::initializer_list constructor). As an example, Python users can create the arrow polynomial A^-4 + (A^-6 - A^-10) K_1 using either of the expressions:

Arrow([([], Laurent(-4, [1])), ([1], Laurent(-10, [-1,0,0,0,1]))])
Arrow([([], (-4, [1])), ([1], (-10, [-1,0,0,0,1]))])
Python
Instead of the iterators begin and end, this routine takes a python list of pairs (seq, laurent), where seq is a python list of integers representing a diagram sequence, and where laurent is either (i) a Laurent polynomial, or (ii) a pair (minExp, coefficients) which could be used to construct a Laurent polynomial. In the latter case, minExp would an integer, and coefficients would be a python list of integers.
Precondition
No diagram sequence ends in zero.
Exceptions
InvalidArgumentAt least one of the given diagram sequences is non-empty and ends in zero.
Template Parameters
iteratoran iterator type which, when dereferenced, gives a std::pair of the form (seq, laurent), where seq and laurent can be used to construct objects of types DiagramSequence and Laurent<Integer> respectively.
derefa dummy argument that should be ignored. This is present to ensure that iterator can be dereferenced. Once we support a greater subset of C++20, this will be enforced through concepts instead.
Parameters
beginthe beginning of the collection of pairs, as outlined above.
enda past-the-end iterator indicating the end of the collection of pairs.

◆ Arrow() [5/6]

regina::Arrow::Arrow ( std::initializer_list< std::pair< DiagramSequence, Laurent< Integer > > > pairs)
inline

Creates a new polynomial from a hard-coded collection of diagram sequences and non-zero Laurent polynomials in A.

The data should be presented as a collection of pairs of the form (seq, laurent), where seq is a diagram sequence and laurent is the associated Laurent polynomial in A.

The pairs may be given in any order. An empty sequence will be treated as the zero polynomial.

So, for example, you can create the arrow polynomial A^-4 + (A^-6 - A^-10) K_1 using the syntax:

Arrow a = { {{}, {-4, {1}}}, {{1}, {-10, {-1,0,0,0,1}}} };
Represents a multivariate polynomial of the type used by arrow polynomials of links.
Definition arrow.h:72
Precondition
The diagram sequences are all distinct, no diagram sequence ends in zero, and each associated Laurent polynomial is non-zero.
Python
Not present. Instead, use the Python constructor that takes a list of pairs (which need not be constant).
Exceptions
InvalidArgumentTwo of the given diagram sequences are identical, and/or one of the given diagram sequences is non-empty and ends in zero, and/or one of the given Laurent polynomials is zero.
Parameters
pairsthe diagram sequences and Laurent polynomials, as outlined above.

◆ Arrow() [6/6]

regina::Arrow::Arrow ( Laurent< Integer > laurent)
inline

Creates the given Laurent polynomial in A.

This polynomial will have no diagram variables at all.

Parameters
laurentthe value of this new polynomial, given as a Laurent polynomial in A.

Member Function Documentation

◆ detail()

std::string regina::Output< Arrow, supportsUtf8 >::detail ( ) const
inherited

Returns a detailed text representation of this object.

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

Returns
a detailed text representation of this object.

◆ hash()

size_t regina::TightEncodable< Arrow >::hash ( ) const
inlineinherited

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

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

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

◆ init()

void regina::Arrow::init ( )
inline

Sets this to become the zero polynomial.

◆ initDiagram() [1/2]

void regina::Arrow::initDiagram ( const DiagramSequence & d)
inline

Sets this to become the given product of diagram variables, using a deep copy.

If d is the sequence a_1,a_2,..., then this polynomial will be set to (K_1)^(a_1) (K_2)^(a_2) ....

Exceptions
InvalidArgumentThe given sequence of integers is non-empty and its last entry is zero.
Parameters
da sequence of integers representing some product of diagram variables. If this sequence is non-empty, then its last entry should be strictly positive.

◆ initDiagram() [2/2]

void regina::Arrow::initDiagram ( DiagramSequence && d)
inline

Sets this to become the given product of diagram variables, using a fast move operation.

This variant of initDiagram() will move the diagram sequence out of the argument d, which is very fast; however, like any move operation, it will render the original argument d unusable.

If d is the sequence a_1,a_2,..., then this polynomial will be set to (K_1)^(a_1) (K_2)^(a_2) ....

Python
Not present. Only the copying variant of initDiagram() is available to Python users (not this move variant).
Exceptions
InvalidArgumentThe given sequence of integers is non-empty and its last entry is zero.
Parameters
da sequence of integers representing some product of diagram variables. If this sequence is non-empty, then its last entry should be strictly positive.

◆ invertA()

void regina::Arrow::invertA ( )
inline

Replaces A with A^-1 in this polynomial.

This polynomial is changed directly.

Calling this routine is equivalent to calling scaleUp(-1).

◆ isZero()

bool regina::Arrow::isZero ( ) const
inline

Returns whether this is the zero polynomial.

Returns
true if and only if this is the zero polynomial.

◆ multDiagram()

void regina::Arrow::multDiagram ( size_t index)

Multiplies this polynomial by the given diagram variable.

Specifically, if the given index is i, then this polynomial will be multiplied by the diagram variable K_i. Note that this requires i to be strictly positive.

Exceptions
InvalidArgumentThe given index is zero.
Parameters
indexthe index of the diagram variable to multiply by; this must be strictly positive.

◆ negate()

void regina::Arrow::negate ( )
inline

Negates this polynomial.

This polynomial is changed directly.

◆ operator*=() [1/3]

Arrow & regina::Arrow::operator*= ( const Arrow & other)
inline

Multiplies this by the given polynomial.

Parameters
otherthe polynomial to multiply this by.
Returns
a reference to this polynomial.

◆ operator*=() [2/3]

Arrow & regina::Arrow::operator*= ( const Integer & scalar)
inline

Multiplies this polynomial by the given integer constant.

Parameters
scalarthe scalar factor to multiply by.
Returns
a reference to this polynomial.

◆ operator*=() [3/3]

Arrow & regina::Arrow::operator*= ( const Laurent< Integer > & laurent)
inline

Multiplies this arrow polynomial by the given Laurent polynomial in A.

Parameters
laurentthe Laurent polynomial to multiply by; this will be treated as a Laurent polynomial in the ordinary variable A.
Returns
a reference to this arrow polynomial.

◆ operator+=()

Arrow & regina::Arrow::operator+= ( const Arrow & other)

Adds the given polynomial to this.

Parameters
otherthe polynomial to add to this.
Returns
a reference to this polynomial.

◆ operator-=()

Arrow & regina::Arrow::operator-= ( const Arrow & other)

Subtracts the given polynomial from this.

Parameters
otherthe polynomial to subtract from this.
Returns
a reference to this polynomial.

◆ operator<=>()

std::strong_ordering regina::Arrow::operator<=> ( const Arrow & rhs) const
inline

Compares this against the given polynomial under a total ordering of all arrow polynomials.

The particular total order that Regina uses is not important, and may change between Regina releases (though such changes should be very infrequent). The main purpose of this routine is to support algorithms that require a "canonical" choice of polynomial from amongst many alternatives.

This routine generates all of the usual comparison operators, including <, <=, >, and >=.

Python
This spaceship operator x <=> y is not available, but the other comparison operators that it generates are available.
Parameters
rhsthe polynomial to compare with this.
Returns
The result of the comparison between this and the given polynomial.

◆ operator=() [1/3]

Arrow & regina::Arrow::operator= ( Arrow && value)
defaultnoexcept

Moves the contents of the given polynomial to this polynomial.

This is a fast (constant time) operation.

The polynomial that was passed will no longer be usable.

Returns
a reference to this polynomial.

◆ operator=() [2/3]

Arrow & regina::Arrow::operator= ( const Arrow & )
default

Sets this to be a copy of the given polynomial.

This operator induces a deep copy of the given polynomial.

Returns
a reference to this polynomial.

◆ operator=() [3/3]

Arrow & regina::Arrow::operator= ( Laurent< Integer > laurent)
inline

Sets this to be the given Laurent polynomial in A.

This polynomial will have no diagram variables at all.

Parameters
laurentthe new value of this polynomial, given as a Laurent polynomial in A.
Returns
a reference to this polynomial.

◆ operator==() [1/2]

bool regina::Arrow::operator== ( const Arrow & rhs) const
inline

Tests whether this and the given polynomial are equal.

Parameters
rhsthe polynomial to compare with this.
Returns
true if and only if this and the given polynomial are equal.

◆ operator==() [2/2]

bool regina::Arrow::operator== ( const Laurent< Integer > & rhs) const
inline

Tests whether this is equal to the given Laurent polynomial in A.

For this to be true, this polynomial must not use any of the diagram variables K_i at all.

Parameters
rhsthe Laurent polynomial in A to compare this with.
Returns
true if and only if this and the given Laurent polynomial are equal.

◆ operator[]()

const Laurent< Integer > & regina::Arrow::operator[] ( const DiagramSequence & d) const

Returns the Laurent polynomial in A that is attached to the given product of diagram variables.

Python
The diagram sequence should be presented as a sequence of integer arguments; that is, you should write arrow[a1, a2, ...]. Moreover, in Python this operator can also set the attached Laurent polynomial: you can write arrow[a1, a2, ...] = .... However, when getting a coefficient this operator will return by value (to enforce constness), which means for example you cannot write something like arrow[a1, a2, ...].negate().
C++
For C++ users, this operator is read-only. To set coefficients, you must use the separate routine set().
Exceptions
InvalidArgumentThe given sequence of integers is non-empty and its last entry is zero.
Parameters
da sequence of integers representing some product of diagram variables. If this sequence is non-empty, then its last entry should be strictly positive.
Returns
the Laurent polynomial attached to the given product of diagram variables.

◆ scaleDown()

void regina::Arrow::scaleDown ( long k)
inline

Divides all exponents in this polynomial by k for some integer k.

This is equivalent to replacing the variable A with A^(1/k).

Both positive and negative scaling factors k are allowed.

Precondition
k is non-zero.
All exponents of A that appear in this polynomial with non-zero coefficients are multiples of k.
Exceptions
FailedPreconditionEither k is zero, or some exponent of A with a non-zero coefficient is not a multiple of k.
Parameters
kthe scaling factor to divide exponents by.

◆ scaleUp()

void regina::Arrow::scaleUp ( long k)
inline

Multiplies all exponents of A in this polynomial by k for some integer k.

This is equivalent to replacing the variable A with A^k.

Both positive and negative scaling factors k are allowed.

Precondition
k is non-zero.
Parameters
kthe scaling factor to multiply exponents by.

◆ set() [1/2]

void regina::Arrow::set ( const DiagramSequence & d,
const Laurent< Integer > & value )

Changes the Laurent polynomial in A that is attached to the given product of diagram variables.

The new coefficient is allowed to be zero.

Python
The diagram sequence should be presented as a sequence of integer arguments; that is: arrow.set(a1, a2, ...) = value. In Python (but not C++), you can also set the attached Laurent polynomial directly using the syntax arrow[a1, a2, ...] = value.
Exceptions
InvalidArgumentThe given sequence of integers is non-empty and its last entry is zero.
Parameters
da sequence of integers representing some product of diagram variables. If this sequence is non-empty, then its last entry should be strictly positive.
valuethe new Laurent polynomial that should be attached to the given product of diagram variables.

◆ set() [2/2]

void regina::Arrow::set ( const DiagramSequence & d,
Laurent< Integer > && value )

Changes the Laurent polynomial in A that is attached to the given product of diagram variables.

This variant of set() will move the Laurent polynomial out of the argument value, which is very fast; however, like any move operation, it will render the original argument value unusable.

The new coefficient is allowed to be zero.

Python
Not present. Only the copying variant of set() is available to Python users (not this move variant). Note that in Python (but not C++), you can also set the attached Laurent polynomial directly using the syntax arrow[a1, a2, ...] = value.
Exceptions
InvalidArgumentThe given sequence of integers is non-empty and its last entry is zero.
Parameters
da sequence of integers representing some product of diagram variables. If this sequence is non-empty, then its last entry should be strictly positive.
valuethe new Laurent polynomial that should be attached to the given product of diagram variables.

◆ shift()

void regina::Arrow::shift ( long s)
inline

Multiplies this polynomial by A^s for some integer s.

Parameters
sthe power of A to multiply by.

◆ str()

std::string regina::Output< Arrow, supportsUtf8 >::str ( ) const
inherited

Returns a short text representation of this object.

This text should be human-readable, should use plain ASCII characters where possible, and should not contain any newlines.

Within these limits, this short text ouptut should be as information-rich as possible, since in most cases this forms the basis for the Python __str__() and __repr__() functions.

Python
The Python "stringification" function __str__() will use precisely this function, and for most classes the Python __repr__() function will incorporate this into its output.
Returns
a short text representation of this object.

◆ sumLaurent()

Laurent< Integer > regina::Arrow::sumLaurent ( ) const
inline

Returns the sum of all Laurent polynomials in A that are attached to each diagram sequence.

This is the Laurent polynomial in A that would be obtained if we set each diagram variable K_i = 1.

Returns
the sum of all attached Laurent polynomials in A.

◆ swap()

void regina::Arrow::swap ( Arrow & other)
inlinenoexcept

Swaps the contents of this and the given polynomial.

This is a fast (constant time) operation.

Parameters
otherthe polynomial whose contents should be swapped with this.

◆ tightDecode()

static Arrow regina::Arrow::tightDecode ( std::istream & input)
static

Reconstructs a polynomial from its given tight encoding.

See the page on tight encodings for details.

The tight encoding will be read from the given input stream. If the input stream contains leading whitespace then it will be treated as an invalid encoding (i.e., this routine will throw an exception). The input stream may contain further data: if this routine is successful then the input stream will be left positioned immediately after the encoding, without skipping any trailing whitespace.

Exceptions
InvalidInputThe given input stream does not begin with a tight encoding of an arrow polynomial.
Python
Not present. Use tightDecoding() instead, which takes a string as its argument.
Parameters
inputan input stream that begins with the tight encoding for an arrow polynomial.
Returns
the polynomial represented by the given tight encoding.

◆ tightDecoding()

static Arrow regina::TightEncodable< Arrow >::tightDecoding ( const std::string & enc)
inlinestaticinherited

Reconstructs an object of type T from its given tight encoding.

See the page on tight encodings for details.

The tight encoding should be given as a string. If this string contains leading whitespace or any trailing characters at all (including trailing whitespace), then it will be treated as an invalid encoding (i.e., this routine will throw an exception).

Exceptions
InvalidArgumentThe given string is not a tight encoding of an object of type T.
Parameters
encthe tight encoding for an object of type T.
Returns
the object represented by the given tight encoding.

◆ tightEncode()

void regina::Arrow::tightEncode ( std::ostream & out) const

Writes the tight encoding of this polynomial to the given output stream.

See the page on tight encodings for details.

Python
Not present. Use tightEncoding() instead, which returns a string.
Parameters
outthe output stream to which the encoded string will be written.

◆ tightEncoding()

std::string regina::TightEncodable< Arrow >::tightEncoding ( ) const
inlineinherited

Returns the tight encoding of this object.

See the page on tight encodings for details.

Exceptions
FailedPreconditionThis may be thrown for some classes T if the object is in an invalid state. If this is possible, then a more detailed explanation of "invalid" can be found in the class documentation for T, under the member function T::tightEncode(). See FacetPairing::tightEncode() for an example of this.
Returns
the resulting encoded string.

◆ utf8()

std::string regina::Output< Arrow, supportsUtf8 >::utf8 ( ) const
inherited

Returns a short text representation of this object using unicode characters.

Like str(), this text should be human-readable, should not contain any newlines, and (within these constraints) should be as information-rich as is reasonable.

Unlike str(), this function may use unicode characters to make the output more pleasant to read. The string that is returned will be encoded in UTF-8.

Returns
a short text representation of this object.

◆ writeTextLong()

void regina::ShortOutput< Arrow, supportsUtf8 >::writeTextLong ( std::ostream & out) const
inlineinherited

A default implementation for detailed output.

This routine simply calls T::writeTextShort() and appends a final newline.

Python
Not present. Instead you can call detail() from the subclass T, which returns this output as a string.
Parameters
outthe output stream to which to write.

◆ writeTextShort()

void regina::Arrow::writeTextShort ( std::ostream & out,
bool utf8 = false ) const

Writes this polynomial to the given output stream.

If utf8 is passed as true then unicode subscript and superscript characters will be used for diagram variables, exponents and the minus sign; these will be encoded using UTF-8. This will make the output nicer, but will require more complex fonts to be available on the user's machine.

Python
Not present. Use str() or utf8() instead.
Parameters
outthe output stream to which to write.
utf8true if unicode characters may be used.

Friends And Related Symbol Documentation

◆ operator*

Arrow operator* ( const Arrow & lhs,
const Arrow & rhs )
friend

Multiplies the two given polynomials.

Parameters
lhsthe first polynomial to multiply.
rhsthe second polynomial to multiply.
Returns
the product of the two given polynomials.

The documentation for this class was generated from the following file: