Tutorial (test)#

Step-by-step tutorial introducing KnotPy, from installation to constructing knots, links, and computing invariants.

Your first knot#

Create the (unoriented) trefoil knot and draw it.

import knotpy as kp
k = kp.knot("3_1")
kp.draw(k)
../_images/a24ef0211e64396a893f7f67da69bb2b1e6a1017e4e6294ef72fefae426da6f9.png
k.name
'3_1'
kp.identify(k)
'3_1'
kp.jones(k)
\[\displaystyle - t^{4} + t^{3} + t\]
k = kp.knot("trefoil")
kp.identify(k)
'3_1'
k = kp.knot("+3_1")
kp.identify(k)
'+3_1'

Input/Output#

PD code#

k = kp.from_pd_notation("X(4,2,5,1),X(8,6,1,5),X(6,3,7,4),X(2,7,3,8)")
kp.identify(k)
'4_1'
k = kp.from_pd_notation("PD[X[4, 2, 5, 1], X[8, 6, 1, 5], X[6, 3, 7, 4], X[2, 7, 3, 8]]")
kp.identify(k)
'4_1'
k = kp.from_pd_notation([[4,2,5,1],[8,6,1,5],[6,3,7,4],[2,7,3,8]])
kp.identify(k)
'4_1'
kp.to_pd_notation(k)
'X[0,1,2,3],X[4,5,3,2],X[5,6,7,0],X[1,7,6,4]'
k = kp.from_pd_notation("V[1,2,3],V[1,4,5],X[2,6,7,8],X[8,9,4,3],X[9,7,6,5]")
kp.draw(k)
../_images/fefa8cf7a7455ae359ccf445bc31cf3f05cb3d4307ce78926adbebd9cd6ae78f.png
k = kp.from_pd_notation("V[1,2,3],V[1,4,5],X[2,6,7,8],X[8,9,4,3],X[9,7,6,5]")
kp.draw(k)
../_images/fefa8cf7a7455ae359ccf445bc31cf3f05cb3d4307ce78926adbebd9cd6ae78f.png
k = kp.from_pd_notation("V[1],X[1,5,2,4],X[3,7,4,6],X[5,3,6,2],V[7]")
kp.draw(k)
0.25 False
0.25 False
../_images/75284672ba20060b653f115bb6bccf59de8782ee1e5652f97fce4c4051a5db06.png
k = kp.from_pd_notation("X[4,1,3,2],X[1,4,2,3]")
kp.draw(k)
../_images/90c78a053f204b5bfdf538a8836a0b39ce0a753b7d7d9ea12a209eb8a21be01a.png
k = kp.from_pd_notation("X[4,1,3,2],X[1,4,2,3]")
kp.sanity_check(k)
True
k = kp.from_pd_notation("X[4,1,3,2],X[1,3,2,4]")
kp.sanity_check(k)
False

EM code#

EM code#

EM code#

Plantri code#

Native KnotPy code#

Canonical form#

Inport/Export#

Drawing#

Operations#

Connected sum#

k31 = kp.knot("3_1")
k41 = kp.knot("4_1")
k_sum = kp.connected_sum(k31, k41)
kp.is_connected_sum(k_sum)
True
a, b = kp.connected_sum_decomposition(k_sum)
kp.identify(a), kp.identify(b)
('3_1', '4_1')

Disjoint union#

k_union = kp.disjoint_union(k31, k41)
kp.is_disjoint_union(k_union)
True
a, b = kp.disjoint_union_decomposition(k_union)
kp.identify(a), kp.identify(b)
('3_1', '4_1')

Symmetry#

k = kp.knot("3_1")
kp.symmetry_type(k)
'reversible'
kp.symmetry_type("9_32")
'chiral'
[k.name for k in kp.knots(range(10)) if kp.symmetry_type(k) == "chiral"]
['9_32', '9_33']
for n in range(9, 12):
    print("There are", len([k for k in kp.knots(n) if kp.symmetry_type(k) == "chiral"]), "chiral knots with", n, "crossings.")
There are 2 chiral knots with 9 crossings.
There are 27 chiral knots with 10 crossings.
There are 187 chiral knots with 11 crossings.

Mirror#

k = kp.knot("3_1")
k_mirror = kp.mirror(k)
kp.identify(k_mirror)
'3_1*'
k = kp.knot("4_1")
k_mirror = kp.mirror(k)
kp.identify(k_mirror)
'4_1'

Orientation#

k = kp.knot("3_1")
k_oriented = kp.orient(k)
kp.identify(k_oriented)
'+3_1'
k_unoriented = kp.unorient(k)
kp.identify(k_unoriented)
'3_1'
k = kp.knot("+3_1")
k_reversed = kp.reverse(k)
kp.identify(k_reversed)
'+3_1'
k = kp.knot("+8_17")
k_reversed = kp.reverse(k)
kp.identify(k_reversed)
'-8_17'
k = kp.knot("L6a5")
kp.draw(k)
../_images/5754745f82ce515b3fc6db686cf154f763432f1805e1fa3118bc7fa325cd4884.png
k = kp.knot("L6a5+--")
kp.draw(k)
../_images/08e4c3fd7d1baef484894ab337eb4f9be247eedd2670e9eb749fb6f8dd5ff65a.png
k = kp.knot("L6a5")
kp.number_of_link_components(k)
3
k_orientations = kp.orientations(k)
len(k_orientations)
8

Flip#

k = kp.from_pd_notation("V[1],X[1,5,2,4],X[3,7,4,6],X[5,3,6,2],V[7]")
k_flipped = kp.flip(k)
kp.canonical(k) == kp.canonical(k_flipped)
True

Invariants#

Spatial (knotted) graph invariants#

k = kp.from_pd_notation("V[1,2,3],V[1,4,5],X[2,6,7,8],X[8,9,4,3],X[9,7,6,5]")
#kp.unplugging()
kp.yamada(k)
k_oriented = kp.orient(k)
g = kp.fundamental_group(k_oriented)
g.generators, g.relators
g = kp.wheel_graph(5)
kp.tutte(g)

Knotoid and linkoid invariants#

k = kp.from_pd_notation("V[1],X[1,5,2,4],X[3,7,4,6],X[5,3,6,2],V[7]")
k.name = "k3_1"
print("Knotoid:", k.name)
print("Affine index polynomial:", kp.affine_index_polynomial(k))
print("Arrow polynomial:", kp.arrow_polynomial(k))
print("Mock Alexander polynomial", kp.mock_alexander_polynomial(k))
print("Kauffman bracket skein module:", kp.kauffman_bracket_skein_module(k, normalize=True))
k_closure = kp.closure(k, over=True, under=True)
kp.yamada(k_closure)

Reidemesiter moves#

Simplifying a diagram#

culprit_unknot =kp.knot("culprit")
kp.draw(culprit_unknot)
kp.identify(culprit_unknot)
k = kp.simplify(culprit_unknot)
len(k.crossings)
kp.is_unknot(k)
goeritz_unknot = kp.knot("goeritz")
kp.draw(goeritz_unknot)
kp.identify(goeritz_unknot)
k = kp.simplify(goeritz_unknot)
len(k.crossings)
k = kp.simplify(goeritz_unknot, depth=2, flype=True)
len(k.crossings)

Reidemeister moves#

Reidemeister moves#

Diagram attributes#

kp.is_knot(K)
%%sql
K = kp.knot("unknot")
K.name
K = kp.knot("+3_1")
K.is_oriented()
K_ = kp.knot("-3_1")
kp.identify(kp.knot("-3_1"))
K = kp.knot("3_1")
print("Knot:", K.name)
print("Jones polynomial:", kp.jones(K))
print("Alexander polynomial:", kp.alexander(K))
print("Bracket polynomial:", kp.bracket(K, normalize=True))
print("HOMFLYPT polynomial:", kp.homflypt(K))
print("HOMFLYPT polynomial (az):", kp.homflypt(K, variables="az"))
print("HOMFLYPT polynomial (lm):", kp.homflypt(K, variables="lm"))
print("HOMFLYPT polynomial (xyz):", kp.homflypt(K, variables="xyz"))
print("Kauffman 2-variable polynomial:", kp.kauffman(K))
K = kp.knot("+3_1")
G = kp.fundamental_group(K)
G.generators, G.relators
K = kp.from_pd_notation("[[1,5,2,4],[3,1,4,6],[5,3,6,2]]")
kp.identify(K)
K = kp.from_pd_notation("PD[X[1,9,2,8], X[3,10,4,11], X[5,3,6,2],X[7,1,8,12], X[9,4,10,5], X[11,7,12,6]]")
kp.identify(K)
kp.to_pd_notation(kp.knot("3_1"))
# EM, CONDENSED EM,... PLANTRI
K = kp.knot("3_1")
kp.identify(kp.orient(K))
[kp.identify(K) for K in kp.orientations(kp.knot("9_32"))]
K = kp.knot("3_1")
kp.identify(kp.mirror(K))
K = kp.knot("+9_32")
kp.identify(kp.reverse(K))
K = kp.knot("+9_32")
K = kp.mirror(kp.reverse(K))
kp.identify(K)