Access to the KnotInfo database

This module contains the class KnotInfoBase which is derived from Enum and provides knots and links listed in the databases at the web-pages KnotInfo and LinkInfo as its items.

This interface contains a set of about twenty knots and links statically as demonstration cases. The complete database can be installed as an optional Sage package using

  • sage -i database_knotinfo (does not install if the current version is present)

  • sage -f database_knotinfo (installs even if the current version is present)

This will install a Python wrapper for the original databases in Sage. This wrapper perfoms an automatic progress of version numbers. For more details and further install instructions please see the correspondig web-page.

To perform all the doctests concerning the usage of the database on the installation add the option -c. In this case (for instance sage -f -c database_knotinfo) the installation breaks on failing tests.

The installation of the complete database will be necessary in order to have access to all the properties recorded in the databases, as well.

If the entire database is installed as explained above, the import instructions for KnotInfo and KnotInfoSeries, which can be seen in the opening lines of the examples, are unnecessary.

Be aware that there are a couple of conventions used differently on KnotInfo as in Sage, especially concerning the selection of the symmetry version of the link.

In this context you should note that the PD notation is recorded counter clockwise in KnotInfo (see note in KnotInfoBase.link()). In our transition to Sage objects this is translated (by default) in order to avoid confusion about exchanged mirror versions.

Also, note that the braid notation is used according to Sage, even thought in the source where it is taken from, the braid generators are assumed to have a negative crossing which would be opposite to the convention in Sage (see definition 3 of Gittings, T., “Minimum Braids: A Complete Invariant of Knots and Links”).

For different conventions regarding normalization of the polynomial invariants see the according documentation of KnotInfoBase.homfly_polynomial(), KnotInfoBase.jones_polynomial() and KnotInfoBase.alexander_polynomial().

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: L = KnotInfo.L4a1_0
sage: L.pd_notation()
[[6, 1, 7, 2], [8, 3, 5, 4], [2, 5, 3, 6], [4, 7, 1, 8]]
sage: L.pd_notation(original=True)
'{{6, 1, 7, 2}, {8, 3, 5, 4}, {2, 5, 3, 6}, {4, 7, 1, 8}}'
sage: L.is_knot()
False
sage: L.num_components()
2

Items for knots need a leading K for technical reason:

sage: K = KnotInfo.K4_1
sage: K.is_knot()
True

Injecting the variable name into the namespace:

sage: KnotInfo.K5_1.inject()
Defining K5_1
sage: K5_1.dt_notation()
[6, 8, 10, 2, 4]

Defining a link from the original name string:

sage: KnotInfo('L6a1{1}').inject()
Defining L6a1_1
sage: L6a1_1.is_alternating()
True

Obtaining an instance of Braid:

sage: L.braid()
s1^-2*s0^-1*s1*s0^-1
sage: type(_)
<class 'sage.groups.braid.BraidGroup_class_with_category.element_class'>

Obtaining an instance of Link:

sage: l = L.link(); l
Link with 2 components represented by 4 crossings
sage: type(l)
<class 'sage.knots.link.Link'>

If you have SnapPy installed inside Sage you can obtain an instance of Link, too:

sage: L6 = KnotInfo.L6a1_0
sage: l6s = L6.link(snappy=True); l6s      # optional - snappy
Plink failed to import tkinter.
<Link: 2 comp; 6 cross>

sage: type(l6s)                            # optional - snappy
<class 'spherogram.links.invariants.Link'>
sage: l6  = L6.link().mirror_image()
sage: l6 == l6s.sage_link()                # optional - snappy
True
sage: L6.link(L6.items.name, snappy=True)  # optional - snappy
<Link L6a1: 2 comp; 6 cross>
sage: l6sn = _                             # optional - snappy
sage: l6s == l6sn                          # optional - snappy
False
sage: l6sn.sage_link().is_isotopic(l6)     # optional - snappy
True

But observe that the name conversion to SnapPy does not distingiush orientation types:

sage: L6b = KnotInfo.L6a1_1
sage: L6b.link(L6b.items.name, snappy=True)  # optional - snappy
<Link L6a1: 2 comp; 6 cross>
sage: _.PD_code() == l6sn.PD_code()          # optional - snappy
True

Obtaining the HOMFLY-PT polynomial:

sage: L.homfly_polynomial()
-v^-1*z - v^-3*z - v^-3*z^-1 + v^-5*z^-1
sage: _ == l.homfly_polynomial(normalization='vz')
True

Obtaining the original string from the database for an arbitrary property:

sage: K[K.items.classical_conway_name]  # optional - database_knotinfo
'4_1'

Further methods:

sage: K.crossing_number()
4
sage: K.gauss_notation()
[-1, 2, -3, 1, -4, 3, -2, 4]
sage: K.dt_notation()
[4, 6, 8, 2]
sage: K.determinant()
5
sage: K.symmetry_type()
'fully amphicheiral'
sage: _ == K[K.items.symmetry_type]
True
sage: K.is_reversible()
True
sage: K.is_amphicheiral()
True
sage: K.jones_polynomial()
t^2 - t - 1/t + 1/t^2 + 1
sage: K.kauffman_polynomial()
a^2*z^2 + a*z^3 - a^2 - a*z + 2*z^2 + a^-1*z^3 - 1 - a^-1*z + a^-2*z^2 - a^-2
sage: K.alexander_polynomial()
t^2 - 3*t + 1

Using the column_type of a property:

sage: def select_column(i):
....:     return i.column_type() != i.types.OnlyLinks and K[i] == 'Y'
sage: [i.column_name() for i in K.items if select_column(i)]  # optional - database_knotinfo
['Alternating', 'Fibered', 'Quasialternating', 'Adequate']

You can launch web-pages attached to the links:

sage: K.diagram()                 # not tested
True
sage: L.diagram(single=True)      # not tested
True
sage: L.knot_atlas_webpage()      # not tested
True
sage: K.knotilus_webpage()        # not tested
True

and the description web-pages of the properties:

sage: K.items.positive.description_webpage()  # not tested
True

To see all the properties available in this interface you can use “tab-completion”. For example type K.items. and than hit the “tab-key”. You can select the item you want from the list. If you know some first letters type them first to obtain a reduced selection list.

In a similar way you may select the knots and links. Here you have to type KnotInfo. or KnotInfo.L7 before stroking the “tab-key”. In the latter case the selection list will be reduced to proper links with 7 crossings.

Finally there is a method Link.get_knotinfo() of class Link to find an instance in the KnotInfo database:

sage: L = Link([[3,1,2,4], [8,9,1,7], [5,6,7,3], [4,18,6,5],
....:           [17,19,8,18], [9,10,11,14], [10,12,13,11],
....:           [12,19,15,13], [20,16,14,15], [16,20,17,2]])
sage: L.get_knotinfo()
(<KnotInfo.K0_1: '0_1'>, None)

REFERENCES:

AUTHORS:

  • Sebastian Oehms August 2020: initial version

Thanks to Chuck Livingston and Allison Moore for their support. For further acknowledgments see the correspondig hompages.

class sage.knots.knotinfo.KnotInfo

Bases: sage.knots.knotinfo.KnotInfoBase

An enumeration.

class sage.knots.knotinfo.KnotInfoBase

Bases: enum.Enum

Enum class to select the knots and links listed in the databases at the web-pages KnotInfo and LinkInfo.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: [knot.name for knot in KnotInfo if knot.crossing_number() < 5]
['K0_1', 'K3_1', 'K4_1', 'L2a1_0', 'L2a1_1', 'L4a1_0', 'L4a1_1']

More examples and information can be seen in the module header knotinfo (by typing):

sage: import sage.knots.knotinfo   # not tested
sage: sage.knots.knotinfo?         # not tested
alexander_polynomial(var='t', original=False, laurent_poly=False)

Return the Alexander polynomial according to the value of column alexander_polynomial for this knot as an instance of Polynomial.

It is obtained from the Seifert matrix \(V\) of self by the following formula (see the KnotInfo description web-page; to launch it see the example below):

\[A(L) = \det(V -t V^t)\]

Here \(V^t\) stands for the transpose of \(V\).

INPUT:

  • var – (default: 't') the variable

  • original – boolean (optional, default False) if set to True the original table entry is returned as a string

  • laurent_poly – boolean (default False) see the note below

OUTPUT:

A polynomial over the integers, more precisely an instance of Polynomial. If laurent_poly is set to True a Laurent polynomial over the integers, more precisely an instance of LaurentPolynomial is returned. If original is set to True then a string is returned.

Note

As an invariant the Alexander polynomial is only unique up to a unit factor in the Laurent polynomial ring over the integers in the indeterminate \(t\). While the normalization of the exponents in KnotInfo guarantees it to be a proper polynomial, this is not the case for the implementation in Sage. Use the keyword laurent_poly to achiev a normalization according to Sage. But, still there may be a difference in sign (see the example below).

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: K = KnotInfo.K4_1
sage: Ka = K.alexander_polynomial(); Ka
t^2 - 3*t + 1

Comparison with Sage’s results:

sage: k = K.link()
sage: ka = k.alexander_polynomial(); ka
-t^-1 + 3 - t
sage: K.alexander_polynomial(laurent_poly=True)
t^-1 - 3 + t
sage: _ == -ka
True

Launch the KnotInfo description web-page:

sage: K.items.alexander_polynomial.description_webpage() # not tested
True
braid()

Return the braid notation of self as an instance of Braid.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: K = KnotInfo.K3_1
sage: K.braid()
s^3
sage: K.braid_notation()
(1, 1, 1)
braid_index()

Return the value of column braid_index for this link as a Python int.

OUTPUT:

Python int giving the minimum of strands needed to represent self as closure of a braid.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: L = KnotInfo.L4a1_0
sage: L.braid_index()
3
braid_length()

Return the value of column braid_length for this link as a Python int.

OUTPUT:

Python int giving the minimum length of a braid word needed to represent self as closure of a braid.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: K = KnotInfo.K3_1
sage: K.braid_length()
3
braid_notation(original=False)

Return the value of column braid_notation for this link as a Python tuple (Tietze form). For more information type KnotInfo.K0_1.items.braid_notation.description_webpage().

INPUT:

  • original – boolean (optional, default False) if set to True the original table entry is returned as a string

OUTPUT:

Python tuple representing the braid whose closure is self in Tietze form.

..NOTE:

There has been a major change to braid representatives for
proper links since version 2021.10.1. The former braid
reresentatives can be obtained by the column
``braid_notation_old`` (see the final example below).

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: L = KnotInfo.L4a1_0
sage: L.braid_notation()
(-2, -2, -1, 2, -1)
sage: L.braid_notation(original=True)
'{3, {-2, -2, -1, 2, -1}}'
sage: L[L.items.braid_notation_old]
'{4, {1, -2, 3, -2, -1, -2, -3, -2}}'
crossing_number()

Return the minimal number of crossings of self.

Note

In contrast to the number of crossings displayed for instances of Link this number is the minimum over all possible diagrams of the link. The number of crossings displayed in the representation string of Link refers to the special diagram which could be larger.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.L4a1_0.crossing_number()
4
sage: KnotInfo.K3_1.crossing_number()
3
sage: Link(KnotInfo.L4a1_0.braid())
Link with 2 components represented by 5 crossings
determinant()

Return the determinant of self.

From the KnotInfo description page:

The determinant of a knot is \(\det(V + V^t)\), where \(V\) is a Seifert matrix for the knot.

To read the complete description type KnotInfo.K0_1.items.determinant.description_webpage().

Note

KnotInfo’s value for the unknot 0_1 is zero. This is not compatible whith Sage’s result (the value of the Alexander polynomial at -1). Since this method is needed to identify Sage links we take the according value in that case.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.L4a1_0.determinant()
4
sage: KnotInfo.K3_1.determinant()
3
sage: KnotInfo.K0_1.determinant()
1
diagram(single=False, new=0, autoraise=True)

Launch the diagram of self given on the KnotInfo web-page.

INPUT:

  • single – boolean (default False) if set to True only one diagram is shown.

  • newint according to open() of webbrowser (0 default, 1 new window, 2 new tab)

  • autoraise – boolean (default True)

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: K = KnotInfo.K3_1
sage: K.diagram()            # not tested
True
sage: K.diagram(single=True) # not tested
True
dt_notation(original=False)

Return the value of column dt_notation for this link as a Python list of Python lists. For more information type KnotInfo.K0_1.items.dt_notation.description_webpage().

INPUT:

  • original – boolean (optional, default False) if set to True the original table entry is returned as a string

OUTPUT:

Python list of python lists each entry of the outer list representing a crossing.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: L = KnotInfo.L4a1_0
sage: L.dt_notation()
[[6, 8], [2, 4]]
sage: L.dt_notation(original=True)
'[{6, 8}, {2, 4}]'
sage: L = KnotInfo.L4a1_0
sage: K = KnotInfo.K4_1
sage: K.dt_notation()
[4, 6, 8, 2]
gauss_notation(original=False)

Return the value of column gauss_notation for this link as a Python list of Python lists. For more information type KnotInfo.K0_1.items.gauss_notation.description_webpage().

INPUT:

  • original – boolean (optional, default False) if set to True the original table entry is returned as a string

OUTPUT:

Python list of

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: L = KnotInfo.L4a1_0
sage: L.gauss_notation()
[[1, -3, 2, -4], [3, -1, 4, -2]]
sage: L.gauss_notation(original=True)
'{{1, -3, 2, -4}, {3, -1, 4, -2}}'
homfly_polynomial(var1='v', var2='z', original=False)

Return the HOMFLY-PT polynomial according to the value of column homfly_polynomial for this knot or link (in the latter case the column homflypt_polynomial is used) as an instance of the element class according to the output of Link.homfly_polynomial() of Link.

The HOMFLY-PT polynomial \(P(L)\) of a link \(L\) satisfies the following skein relation (see the corresponding KnotInfo description page):

\[P(O) = 1,\,\,\, v^{-1} P(L_+) - v P(L_-) = z P(L_0)\]

INPUT:

  • var1 – string (default v) for the name of the first variable

  • var2 – string (default z) for the name of the second variable

  • original – boolean (default False) if set to True the original table entry is returned as a string

OUTPUT:

A Laurent polynomial over the integers, more precisely an instance of LaurentPolynomial_mpair. If original is set to True then a string is returned.

Note

The skein-relation for the HOMFLY-PT polynomial given on KnotInfo does not match the default used in Sage. For comparison you have to use the keyword argument normalization='vz' on the side of Sage.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: K3_1 = KnotInfo.K3_1
sage: PK3_1 = K3_1.homfly_polynomial(); PK3_1
-v^4 + v^2*z^2 + 2*v^2
sage: K3_1.homfly_polynomial(original=True)
'(2*v^2-v^4)+(v^2)*z^2'
sage: PK3_1 == K3_1.link().homfly_polynomial(normalization='vz')
True

for proper links:

sage: L4a1_1 = KnotInfo.L4a1_1
sage: PL4a1_1 = L4a1_1.homfly_polynomial(var1='x', var2='y'); PL4a1_1
-x^5*y + x^3*y^3 - x^5*y^-1 + 3*x^3*y + x^3*y^-1
sage: _ == L4a1_1.link().homfly_polynomial('x', 'y', 'vz')
True

check the skein-relation from the KnotInfo description page (applied to one of the positive crossings of the right-handed trefoil):

sage: R = PK3_1.parent()
sage: PO = R.one()
sage: L2a1_1 = KnotInfo.L2a1_1
sage: PL2a1_1 = L2a1_1.homfly_polynomial()
sage: v, z = R.gens()
sage: ~v*PK3_1 -v*PO == z*PL2a1_1
True

REFERENCES:

inject(verbose=True)

Inject self with its name into the namespace of the Python code from which this function is called.

INPUT:

  • verbose – boolean (optional, default True) to suppress the message printed on the invocation

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K5_2.inject()
Defining K5_2
sage: K5_2.is_alternating()
True
is_adequate()

Return whether self is adequate.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K5_2.is_adequate()         # optional - database_knotinfo
True
is_almost_alternating()

Return whether self is almost alternating.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K5_2.is_almost_alternating() # optional - database_knotinfo
False
is_alternating()

Return whether self is alternating.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K5_2.is_alternating()
True
is_amphicheiral(positive=False)

Return whether self is amphicheiral.

INPUT:

  • positive – boolean (optional, default False) whether to check if self is positive or negative amphicheiral (see documentation of symmetry_type())

OUTPUT:

Boolean or None if this cannot be determined.

True if self is fully or negative amphicheiral per default. If positive is set to True than fully and positive amphicheiral links give True.

Note

For proper links this property is not provided in the database. Anyway, we support it here in this case, as well, except for a few items where it cannot be determined easily and where None is returned as answer.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: Kp = KnotInfo.K12a_427             # optional - database_knotinfo
sage: Kp.is_amphicheiral()               # optional - database_knotinfo
False
sage: Kp.is_amphicheiral(positive=True)  # optional - database_knotinfo
True

sage: Kn = KnotInfo.K10_88               # optional - database_knotinfo
sage: Kn.is_amphicheiral()               # optional - database_knotinfo
True
sage: Kn.is_amphicheiral(positive=True)  # optional - database_knotinfo
False

sage: KnotInfo.L4a1_0.is_amphicheiral()
False
sage: KnotInfo.L10n59_1.is_amphicheiral() # optional - database_knotinfo
True
sage: KnotInfo.L10n36_0.inject()          # optional - database_knotinfo
Defining L10n36_0
sage: L10n36_0.is_amphicheiral() is None  # optional - database_knotinfo
True
is_fibered()

Return whether self is fibered.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K6_3.is_fibered()
True
is_knot()

Return whether self is a knot or a proper link.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.L7a1_0.is_knot()      # optional - database_knotinfo
False
sage: KnotInfo.K6_3.is_knot()
True
is_oriented()

Return whether self is oriented.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.L6a2_1.is_oriented()
True
is_positive()

Return whether self is positive.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K5_2.is_positive()
True
is_positive_braid()

Return whether self is a positive braid.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K5_2.is_positive_braid()         # optional - database_knotinfo
False
is_quasi_alternating()

Return whether self is quasi alternating.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K5_2.is_quasi_alternating() # optional - database_knotinfo
True
is_quasipositive()

Return whether self is quasi-positive.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K5_2.is_quasipositive()     # optional - database_knotinfo
True
is_recoverable(unique=True)

Return if self can be recovered from its conversion to Sage links using the pd_notation and the braid_notation and their mirror images.

The method is indirectly used by the TestSuite of the series of self.

INPUT:

  • unique – boolean (optional, default=``True``) if set to False it is only checked if self is among the recovered items

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.L4a1_0.inject()
Defining L4a1_0
sage: L4a1_0.is_recoverable()
True
sage: L4a1_0.is_recoverable(unique=False)
True
sage: KnotInfo.L5a1_0.inject()
Defining L5a1_0
sage: L5a1_0.is_recoverable()
False
sage: L5a1_0.is_recoverable(unique=False)
True
is_reversible()

Return whether self is reversible.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K6_3.is_reversible()
True
is_strongly_quasipositive()

Return whether self is strongly quasi-positive.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K5_2.is_strongly_quasipositive() # optional - database_knotinfo
True
is_unique()

Return whether there is no other isotopic link in the database or not.

OUTPUT:

Boolean or None if this cannot be determined.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.L4a1_0.is_unique()
True
sage: KnotInfo.L5a1_0.is_unique()
False
sage: L = KnotInfo.L9a43_0_1             # optional - database_knotinfo
sage: L.series(oriented=True).inject()   # optional - database_knotinfo
Defining L9a43
sage: [(L,L.is_unique()) for L in L9a43] # optional - database_knotinfo
[(<KnotInfo.L9a43_0_0: 'L9a43{0,0}'>, True),
 (<KnotInfo.L9a43_1_0: 'L9a43{1,0}'>, False),
 (<KnotInfo.L9a43_0_1: 'L9a43{0,1}'>, None),
 (<KnotInfo.L9a43_1_1: 'L9a43{1,1}'>, False)]
items

Return an Enum class to select a column item of the KnotInfo database.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: L = KnotInfo.L4a1_0
sage: it = L.items
sage: [i.name for i in it if i.name.startswith('braid')]
['braid_index', 'braid_length', 'braid_notation', 'braid_notation_old']
sage: L.items.dt_notation.column_name()
'DT Notation'

To check if the item is available for proper links or only knots type:

sage: it.gauss_notation.column_type()
<KnotInfoColumnTypes.KnotsAndLinks: 'B'>
sage: it.dt_notation.column_type()
<KnotInfoColumnTypes.OnlyKnots: 'K'>

To see the description of the item in your web browser type:

sage: it.gauss_notation.description_webpage()    # not tested
True
jones_polynomial(variab=None, skein_normalization=False, puiseux=False, original=False, use_sqrt=False)

Return the Jones polynomial according to the value of column jones_polynomial for this knot or link as an element of the symbolic ring SR or an instance of LaurentPolynomial depending on the keyword skein_normalization. Using the keyword puiseux instead of an element of the symbolic ring an instance of PuiseuxSeries can be returned.

The Jones polynomial \(V(L)\) of a link \(L\) satisfies the following skein relation (see the corresponding KnotInfo description page):

\[V(O) = 1,\,\,\, t^{-1} V(L_+) - t V(L_-) = (t^{\frac{1}{2}} - t^{-\frac{1}{2}}) V(L_0)\]

INPUT:

  • variab – variable (default: None) used according to Link.jones_polynomial()

  • skein_normalization – boolean (default: False) used according to Link.jones_polynomial()

  • puiseux – boolean (default True) only used in case skein_normalization=False. If set to True instead of an element of the symbolic ring an instance of PuiseuxSeries is returned

  • original – boolean (default False) if set to True the original table entry is returned as a string

  • use_sqrt – boolean (default False) see the note below

OUTPUT:

Depends on the keywords (in excluding order):

  • original=True a string according to the original value from the database

  • skein_normalization=True a Laurent polynomial over the integers, more precisely an instance of LaurentPolynomial

  • puiseux=True a puiseux series over the integers, more precisely an instance of PuiseuxSeries

In all other cases an element of the symbolic ring SR.

Note

There is a difference to Sage’s conventions concerning the Jones polynomial in the case of proper links. KnotInfo does not display these polynomials in the indeterminate \(t\) used in the skein relation. Instead a variable \(x\) is used defined by \(x^2 = t\). Sage uses \(t\) in both cases, knots and proper links. Thus, to obtain the Jones polynomial for a proper link in \(t\) you have to set the keyword use_sqrt to True.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: K = KnotInfo.K4_1
sage: Kj = K.jones_polynomial(); Kj
t^2 - t - 1/t + 1/t^2 + 1
sage: Kjs = K.jones_polynomial(skein_normalization=True); Kjs
A^-8 - A^-4 + 1 - A^4 + A^8
sage: Kjp = K.jones_polynomial(puiseux=True); Kjp
t^-2 - t^-1 + 1 - t + t^2

for proper links:

sage: L = KnotInfo.L2a1_1
sage: Lj = L.jones_polynomial(); Lj
-x^5 - x
sage: Ljt = L.jones_polynomial(use_sqrt=True); Ljt
-t^(5/2) - sqrt(t)
sage: Ljp = L.jones_polynomial(puiseux=True); Ljp
-t^(1/2) - t^(5/2)
sage: Ljs = L.jones_polynomial(skein_normalization=True); Ljs
-A^2 - A^10
sage: Lj.parent()
Symbolic Ring
sage: Ljt.parent()
Symbolic Ring
sage: Ljp.parent()
Puiseux Series Ring in t over Integer Ring
sage: Ljs.parent()
Univariate Laurent Polynomial Ring in A over Integer Ring

Comparison with Sage’s results:

sage: k = K.link()
sage: kj = k.jones_polynomial()
sage: bool(Kj == kj)
True
sage: kjs = k.jones_polynomial(skein_normalization=True)
sage: Kjs == kjs
True
sage: l = L.link()
sage: lj = l.jones_polynomial()
sage: bool(Lj == lj)
False
sage: bool(Ljt == lj)   # see note above
True
sage: ljs = l.jones_polynomial(skein_normalization=True)
sage: Ljs == ljs
True

Check the skein-relation from the KnotInfo description page (applied to one of the positive crossings of the right-handed trefoil):

sage: K3_1  = KnotInfo.K3_1
sage: K3_1j = K3_1.jones_polynomial()
sage: L2a1_1j = Ljt     # see note above
sage: R = L2a1_1j.parent()
sage: Oj = R(1)
sage: t = R('t')
sage: lhs = expand(~t*K3_1j - t*Oj)
sage: rhs = expand((sqrt(t) - ~sqrt(t))*L2a1_1j)
sage: bool(lhs == rhs)
True

The same with the Puiseux series version:

sage: K3_1jp = K3_1.jones_polynomial(puiseux=True)
sage: L2a1_1jp = Ljp
sage: R = L2a1_1jp.parent()
sage: Ojp = R(1)
sage: t = R('t')
sage: ~t*K3_1jp - t*Ojp == (t^(1/2)-~t^(1/2))*L2a1_1jp
True

The same in the case of skein normalization (using \(t = A^4\)):

sage: K3_1js = K3_1.jones_polynomial(skein_normalization=True)
sage: L2a1_1js = L.jones_polynomial(skein_normalization=True)
sage: Rs = K3_1js.parent()
sage: Ojs = Rs.one()
sage: A, = Rs.gens()
sage: ~A^4*K3_1js - A^4*Ojs == (A^2-~A^2)*L2a1_1js
True

REFERENCES:

kauffman_polynomial(var1='a', var2='z', original=False)

Return the Kauffman polynomial according to the value of column kauffman_polynomial for this knot or link as an instance of LaurentPolynomial_mpair.

The Kauffman polynomial \(F(L)\) respectivlely its corresponding invariant under regular isotopy \(\Delta (L) = a^{w(L)} F(L)\) where \(w(L)\) is the writhe of the link \(L\) satisfies the following skein relation (see the corresponding KnotInfo description page):

\[\Delta(O) = 1,\,\,\, \Delta(L_+) - \Delta(L_-) = z (\Delta(L_0 + \Delta(L_{\infty}))\]

Furthermore, removing a curl of sign \(\epsilon\) leads to a multiplication of \(\Delta(L)\) with \(a^{\epsilon}\).

INPUT:

  • var1 – (default: 'a') the first variable

  • var2 – (default: 'z') the second variable

  • original – boolean (optional, default False) if set to True the original table entry is returned as a string

OUTPUT:

A Laurent polynomial over the integers, more precisely an instance of LaurentPolynomial_mpair. If original is set to False then a string is returned.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: L = KnotInfo.L2a1_1
sage: L.kauffman_polynomial()
a^-1*z - a^-1*z^-1 + a^-2 + a^-3*z - a^-3*z^-1
sage: K = KnotInfo.K4_1
sage: K.kauffman_polynomial()
a^2*z^2 + a*z^3 - a^2 - a*z + 2*z^2 + a^-1*z^3 - 1 - a^-1*z + a^-2*z^2 - a^-2

Comparison with Jones polynomial:

sage: k    = _
sage: a, z = k.variables()
sage: j    = K.jones_polynomial(skein_normalization=True)
sage: t,   = j.variables()
sage: k.subs(a=-t^3, z=~t+t) == j.subs(t=t^4)
True

Check the skein relation:

sage: K3_1    = KnotInfo.K3_1
sage: FK3_1   = K3_1.kauffman_polynomial()
sage: FL2a1_1 = L.kauffman_polynomial()
sage: z, a    = FK3_1.variables()
sage: ΔK3_1   = FK3_1   * a**K3_1.link().writhe()
sage: ΔL2a1_1 = FL2a1_1 * a**L.link().writhe()
sage: ΔO1p    = a          # unknot with one positive curl
sage: ΔO2n    = a**-2      # unknot with two negative curls
sage: ΔK3_1 + ΔO1p == z*(ΔL2a1_1 + ΔO2n)
True

REFERENCES:

knot_atlas_webpage(new=0, autoraise=True)

Launch the Knot Atlas web-page for self.

INPUT:

  • newint according to open() of webbrowser (0 default, 1 new window, 2 new tab)

  • autoraise – boolean (default True)

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: K = KnotInfo.K3_1
sage: K.knot_atlas_webpage()        # not tested
True
knotilus_webpage(new=0, autoraise=True)

Launch the Knotilus web-page for self.

INPUT:

  • newint according to open() of webbrowser (0 default, 1 new window, 2 new tab)

  • autoraise – boolean (default True)

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: K = KnotInfo.K3_1
sage: K.knotilus_webpage(new=1)   # not tested
True

Return self as an instance of Link or optional spherogram.links.invariants.Link (SnapPy).

INPUT:

  • use_item – (optional, default self.items.pd_notation) instance of KnotInfoColumns to choose the column that should be used to construct the link. Allowed values are:

    • self.items.pd_notation

    • self.items.braid_notation

    • self.items.name (only for snappy=True)

    • self.items.dt_notation (only for knots and snappy=False)

    • self.items.gauss_notation (only for knots and snappy=False)

  • snappy boolean (default False) if set to True the target of the conversion is the pip installable package SnapPy (explicitely, spherogram.links.invariants.Link). If SnapPy is not installed an ImportError is raised. To install SnapPy use sage -pip install snappy.

Note

We use the PD-notation to construct self as default. This ensures that the number of crossings displayed in the representation string of the link coincides with the crossing number as a topological invariant.

But attention: The convention on how the edges are listed are opposite to each other

  • KnotInfo: counter clockwise

  • Sage: clockwise

Therefore, we take the mirror version of the pd_notation!

Furthermore, note that the mirror version may depend on the used KnotInfo-notation. For instance, regarding to the knot 5_1 the Gauss- and the DT-notation refer to the mirror image (see example below).

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: K = KnotInfo.K3_1
sage: K.link()
Knot represented by 3 crossings
sage: _.braid()
s^3
sage: _ == K.braid()
True

using dt_notation:

sage: K.link(use_item=K.items.dt_notation)
Knot represented by 3 crossings
sage: _.braid()
s^3

sage: L = KnotInfo.L4a1_0
sage: L.link()
Link with 2 components represented by 4 crossings

sage: L.link(use_item=L.items.dt_notation)
Traceback (most recent call last):
...
ValueError: Link construction using Columns.dt_notation not possible

using snappy:

sage: K7   = KnotInfo.K7_2
sage: k7s  = K7.link(snappy=True); k7s     # optional - snappy
<Link: 1 comp; 7 cross>
sage: K7.link(K7.items.name, snappy=True)  # optional - snappy
<Link 7_2: 1 comp; 7 cross>
sage: k7sn = _                             # optional - snappy
sage: k7s == k7sn                          # optional - snappy
False
sage: k7s.sage_link().is_isotopic(k7sn.sage_link()) # optional - snappy
True

but observe:

sage: L2  = KnotInfo.L2a1_1
sage: l2  = L2.link()
sage: l2s = L2.link(snappy=True).sage_link()  # optional -  snappy
sage: l2 == l2s                               # optional -  snappy
False
sage: l2 == l2s.mirror_image()                # optional -  snappy
True

using braid_notation:

sage: L2.link(use_item=L.items.braid_notation) == l2
True

observe:

sage: L.link(use_item=L.items.braid_notation)
Link with 2 components represented by 5 crossings

sage: K6_1 = KnotInfo.K6_1
sage: K6_1.link().braid() == K6_1.braid()
False

also observe:

sage: K4_1 = KnotInfo.K4_1
sage: K4_1.link().pd_code()
[[4, 1, 5, 2], [8, 5, 1, 6], [6, 4, 7, 3], [2, 8, 3, 7]]
sage: K4_1.pd_notation()
[[4, 2, 5, 1], [8, 6, 1, 5], [6, 3, 7, 4], [2, 7, 3, 8]]

sage: K5_1 = KnotInfo.K5_1
sage: K5_1.link().braid()
s^5
sage: K5_1.link(K5_1.items.dt_notation).braid()
s^-5
sage: K5_1.link(K5_1.items.gauss_notation).braid()
s^-5
name_unoriented()

Return the the part of the name of self which is independent on the orientation.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.L10a122_1_0.name_unoriented()  # optional - database_knotinfo
'L10a122'
num_components()

Return the number of components of self.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.L6a1_0.num_components()
2
pd_notation(original=False)

Return the value of column pd_notation for this link as a Python list of Python lists. For more information type KnotInfo.K0_1.items.pd_notation.description_webpage().

INPUT:

  • original – boolean (optional, default False) if set to True the original table entry is returned as a string

OUTPUT:

Python list of python lists each entry of the outer list representing a crossing.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: L = KnotInfo.L4a1_0
sage: L.pd_notation()
[[6, 1, 7, 2], [8, 3, 5, 4], [2, 5, 3, 6], [4, 7, 1, 8]]
sage: L.pd_notation(original=True)
'{{6, 1, 7, 2}, {8, 3, 5, 4}, {2, 5, 3, 6}, {4, 7, 1, 8}}'
sage: K = KnotInfo.K4_1
sage: K.pd_notation()
[[4, 2, 5, 1], [8, 6, 1, 5], [6, 3, 7, 4], [2, 7, 3, 8]]
series(oriented=False)

Return the series of links self belongs to.

INPUT:

  • oriented – boolean (default False) it only affects proper links. By default the items of the series will be again series of links collecting all orientation mutants of an unoriented name. To obtain the series of the individual links this keyword has to be set to True.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: K5 = KnotInfo.K5_2.series()
sage: K5(1)
<KnotInfo.K5_1: '5_1'>
sage: KnotInfo.L4a1_1.series().inject()
Defining L4a
sage: L4a(1)
Series of links L4a1
sage: KnotInfo.L4a1_1.series(oriented=True).inject()
Defining L4a1
sage: L4a(1) == L4a1
True
sage: L4a1(1)
<KnotInfo.L4a1_1: 'L4a1{1}'>
signature()

Return the signature of self.

From the KnotInfo description page:

The signature of a knot, \(\sigma (K)\), is equal to \(\sigma (V + V^t)\), the signature of \(V + V^t\) where \(V\) is a Seifert matrix for the knot and \(V^t\) is its transpose.

To read the complete description type KnotInfo.K0_1.items.signatur.description_webpage().

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K5_2.signature()       # optional - databsase_knotinfo
1
symmetry_type()

Return the symmetry type of self.

From the KnotInfo description page:

If a knot is viewed as the oriented diffeomorphism class of an oriented pair, \(K = (S_3, S_1)\), with \(S_i\) diffeomorphic to \(S^i\), there are four oriented knots associated to any particular knot \(K\). In addition to \(K\) itself, there is the reverse, \(K^r = (S_3, -S_1)\), the concordance inverse, \(-K = (-S_3, -S_1)\), and the mirror image, \(K^m = (-S_3, S_1)\). A knot is called reversible if \(K = K^r\), negative amphicheiral if \(K = -K\), and positive amphicheiral if \(K = K^m\).

A knot possessing any two of these types of symmetry has all three. Thus, in the table, a knot is called reversible if that is the only type of symmetry it has, and likewise for negative amphicheiral. If it has none of these types of symmetry it is called chiral, and if it has all three it is called fully amphicheiral.

For prime knots with fewer than 12 crossings, all amphicheiral knots are negative amphicheiral.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K6_1.series().inject()
Defining K6
sage: [(K.name, K.symmetry_type()) for K in K6]
[('K6_1', 'reversible'),
 ('K6_2', 'reversible'),
 ('K6_3', 'fully amphicheiral')]
three_genus()

Return the three genus of self.

From the KnotInfo description page:

The three-genus of a knot is defined to be the minimal genus of a Seifert surface for a knot.

To read the complete description type KnotInfo.K0_1.items.three_genus.description_webpage().

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.K5_2.three_genus()     # optional - databsase_knotinfo
1

Note that this differs from the corresponding result in Sage since the latter is obtained for a Seifert surface that does not have the minimal genus:

sage: KnotInfo.K5_2.link().genus()
3
class sage.knots.knotinfo.KnotInfoSeries(crossing_number, is_knot, is_alternating, name_unoriented=None)

Bases: sage.structure.unique_representation.UniqueRepresentation, sage.structure.sage_object.SageObject

This class can be used to access knots and links via their index according to the series they belong to.

INPUT:

  • crossing_number – integer giving the crossing numer of this series of links

  • is_knot – boolean whether this series is a series of knots or proper links

  • is_alternating – boolean whether this series is restriced to alternating links or not This is not relevant for knots with less than 11 crossings

  • name_unoriented – string restricting the series to all links with that name_unoriented

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfoSeries
sage: K6 = KnotInfoSeries(6, True, True); K6
Series of knots K6
sage: K6(3)
<KnotInfo.K6_3: '6_3'>
sage: list(K6)
[<KnotInfo.K6_1: '6_1'>, <KnotInfo.K6_2: '6_2'>, <KnotInfo.K6_3: '6_3'>]
sage: L6a = KnotInfoSeries(6, False, True); L6a
Series of links L6a
sage: L6a(2)
Series of links L6a2
sage: _.inject()
Defining L6a2
sage: list(L6a2)
[<KnotInfo.L6a2_0: 'L6a2{0}'>, <KnotInfo.L6a2_1: 'L6a2{1}'>]
sage: L6a2(0).series() == L6a
True
sage: L6a2(0) == L6a2('0')
True
inject(verbose=True)

Inject self with its name into the namespace of the Python code from which this function is called.

INPUT:

  • verbose – boolean (optional, default True) to suppress the message printed on the invocation

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfoSeries
sage: KnotInfoSeries(6, True, True).inject()
Defining K6
sage: K6(2)
<KnotInfo.K6_2: '6_2'>
is_recoverable(unique=True, max_samples=8)

Return if all items of self can be recovered from its conversion to Sage links using the pd_notation and the braid_notation and their mirror images.

The method is indirectly used by the TestSuite.

INPUT:

  • unique – boolean (optional, default=``True``) see KnotInfoBase.is_recoverable()

  • max_samples – non negative integer or infinity (optional, default 8) limits the number of items to check (random sample). If set to infinity then no limit is set.

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo
sage: KnotInfo.L4a1_0.series().inject()
Defining L4a
sage: L4a.is_recoverable()
True
sage: L4a.is_recoverable(unique=False)
True
sage: KnotInfo.L5a1_0.series().inject()
Defining L5a
sage: L5a.is_recoverable()
False
sage: L5a.is_recoverable(unique=False)
True
list(oriented=False, comp=None, det=None, homfly=None)

Return this series as a Python list.

INPUT:

  • oriented – boolean (optional, default False) it only affects series of proper links. By default the list items of a series of proper links are again series of links collecting all orientation types of an unoriented name. To obtain the list of the individual links this keyword has to be set to True

  • comp (optional, default None) if given an integer for this keyword the list is restriced to links having the according number of components. This keyword implies oriented=True

  • det (optional, default None) if given an integer for this keyword the list is restriced to links having the according value for its determinant. This keyword implies oriented=True

  • homfly (optional, default None) if given a HOMFLY-PT polynomial having normalization='vz' for this keyword the list is restriced to links having the according value for its HOMFLY-PT polynomial. This keyword implies oriented=True

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfoSeries
sage: K6 = KnotInfoSeries(6, True, True); K6
Series of knots K6
sage: K6.list()
[<KnotInfo.K6_1: '6_1'>, <KnotInfo.K6_2: '6_2'>, <KnotInfo.K6_3: '6_3'>]
sage: KnotInfoSeries(2, False, True).inject()
Defining L2a
sage: L2a.list()
[Series of links L2a1]
sage: L2a.list(oriented=True)
[<KnotInfo.L2a1_0: 'L2a1{0}'>, <KnotInfo.L2a1_1: 'L2a1{1}'>]
lower_list(oriented=False, comp=None, det=None, homfly=None)

Return this series together with all series with smaller crossing number as a Python list.

INPUT:

  • oriented – boolean (optional, default False) see the description for list()

  • comp (optional, default None) see the description for list()

  • det (optional, default None) see the description for list()

  • homfly (optional, default None) see the description for list()

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfoSeries
sage: KnotInfoSeries(5, True, True).lower_list()
[<KnotInfo.K0_1: '0_1'>,
 <KnotInfo.K3_1: '3_1'>,
 <KnotInfo.K4_1: '4_1'>,
 <KnotInfo.K5_1: '5_1'>,
 <KnotInfo.K5_2: '5_2'>]
sage: KnotInfoSeries(4, False, True).lower_list()
[Series of links L2a1, Series of links L4a1]
sage: KnotInfoSeries(4, False, True).lower_list(oriented=True)
[<KnotInfo.L2a1_0: 'L2a1{0}'>,
 <KnotInfo.L2a1_1: 'L2a1{1}'>,
 <KnotInfo.L4a1_0: 'L4a1{0}'>,
 <KnotInfo.L4a1_1: 'L4a1{1}'>]
sage.knots.knotinfo.eval_knotinfo(string, locals={}, to_tuple=True)

Preparse a string from the KnotInfo database and evaluate it by sage_eval.

INPUT:

  • string – string that gives a value of some database entry

  • locals – dictionary of locals passed to sage_eval

EXAMPLES:

sage: from sage.knots.knotinfo import KnotInfo, eval_knotinfo
sage: L = KnotInfo.L4a1_0
sage: L.braid_notation(original=True)
'{3, {-2, -2, -1, 2, -1}}'
sage: eval_knotinfo(_)
(3, (-2, -2, -1, 2, -1))
sage.knots.knotinfo.knotinfo_bool(string)

Preparse a string from the KnotInfo database representing a boolean.

INPUT:

  • string – string that gives a value of some database entry

EXAMPLES:

sage: from sage.knots.knotinfo import knotinfo_bool
sage: knotinfo_bool('Y')
True