Skip to content

Commit

Permalink
Trac #17030: Knot Theory as a part of GSoC 2014.
Browse files Browse the repository at this point in the history
We provide a basic implementation of knots and links such as the Seifert
matrix, Jones and Alexander polynomials.

URL: http://trac.sagemath.org/17030
Reported by: amitjamadagni
Ticket author(s): Amit Jamadagni, Miguel Marco
Reviewer(s): Miguel Marco, Karl-Dieter Crisman, Frédéric Chapoton,
Travis Scrimshaw, Søren Fuglede Jørgensen, John Palmieri
  • Loading branch information
Release Manager authored and vbraun committed Mar 26, 2016
2 parents bbc0be0 + 207d033 commit 84c522e
Show file tree
Hide file tree
Showing 8 changed files with 2,529 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/doc/en/reference/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ Geometry and Topology
* :doc:`Differential Forms <tensor/index>`
* :doc:`Manifolds <manifolds/index>`
* :doc:`Parametrized Surfaces <riemannian_geometry/index>`
* :doc:`Knot Theory <knots/index>`

Number Theory, Algebraic Geometry
---------------------------------
Expand Down
1 change: 1 addition & 0 deletions src/doc/en/reference/knots/conf.py
10 changes: 10 additions & 0 deletions src/doc/en/reference/knots/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Knot Theory
===========

.. toctree::
:maxdepth: 2

sage/knots/knot
sage/knots/link

.. include:: ../footer.txt
2 changes: 2 additions & 0 deletions src/sage/all.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@

from sage.game_theory.all import *

from sage.knots.all import *

from sage.manifolds.all import *

from cysignals.alarm import alarm, cancel_alarm
Expand Down
Empty file added src/sage/knots/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions src/sage/knots/all.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from sage.knots.knot import Knot
from sage.knots.link import Link

228 changes: 228 additions & 0 deletions src/sage/knots/knot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
r"""
Knots
AUTHORS:
- Miguel Angel Marco Buzunariz
- Amit Jamadagni
"""

#*****************************************************************************
# Copyright (C) 2014 Travis Scrimshaw <tscrim at ucdavis.edu>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# http://www.gnu.org/licenses/
#*****************************************************************************

from sage.knots.link import Link
from sage.rings.finite_rings.integer_mod import Mod

class Knot(Link):
"""
A knot.
A knot is defined as embedding of the circle `\mathbb{S}^1` in the
3-dimensional sphere `\mathbb{S}^3`, considered up to ambient isotopy.
They represent the physical idea of a knotted rope, but with the
particularity that the rope is closed. That is, the ends of the rope
are joined.
.. SEEALSO::
:class:`Link`
INPUT:
- ``data`` -- see :class:`Link` for the allowable inputs
- ``check`` -- optional, default ``True``. If ``True``, make sure
that the data define a knot, not a link
EXAMPLES:
We construct the knot `8_{14}` and compute some invariants::
sage: B = BraidGroup(4)
sage: K = Knot(B([1,1,1,2,-1,2,-3,2,-3]))
.. PLOT::
:width: 300 px
B = BraidGroup(4)
K = Knot(B([1,1,1,2,-1,2,-3,2,-3]))
sphinx_plot(K.plot())
::
sage: K.alexander_polynomial()
-2*t^-2 + 8*t^-1 - 11 + 8*t - 2*t^2
sage: K.jones_polynomial()
t^7 - 3*t^6 + 4*t^5 - 5*t^4 + 6*t^3 - 5*t^2 + 4*t + 1/t - 2
sage: K.determinant()
31
sage: K.signature()
-2
REFERENCES:
- :wikipedia:`Knot_(mathematics)`
.. TODO::
- Implement the connect sum of two knots.
- Make a class Knots for the monoid of all knots and have this be an
element in that monoid.
"""
def __init__(self, data, check=True):
"""
Initialize ``self``.
TESTS::
sage: B = BraidGroup(8)
sage: K = Knot(B([-1, -1, -1, 2, 1, -2, 3, -2, 3]))
sage: TestSuite(K).run()
sage: K = Knot(B([1, -2, 1, -2]))
sage: TestSuite(K).run()
sage: K = Knot([[1, 1, 2, 2]])
sage: TestSuite(K).run()
The following is not a knot: it has two components. ::
sage: Knot([[[1, 2], [-2, -1]], [1, -1]])
Traceback (most recent call last):
...
ValueError: the input has more than 1 connected component
sage: Knot([[[1, 2], [-2, -1]], [1, -1]], check=False)
Knot represented by 2 crossings
"""
Link.__init__(self, data)
if check:
if self.number_of_components() != 1:
raise ValueError("the input has more than 1 connected component")

def __repr__(self):
"""
Return a string representation.
EXAMPLES::
sage: B = BraidGroup(8)
sage: K = Knot(B([1, 2, 1, 2]))
sage: K
Knot represented by 4 crossings
sage: K = Knot([[1, 7, 2, 6], [7, 3, 8, 2], [3, 11, 4, 10], [11, 5, 12, 4], [14, 5, 1, 6], [13, 9, 14, 8], [12, 9, 13, 10]])
sage: K
Knot represented by 7 crossings
"""
pd_len = len(self.pd_code())
return 'Knot represented by {} crossings'.format(pd_len)

def dt_code(self):
"""
Return the DT code of ``self``.
ALGORITHM:
The DT code is generated by the following way:
Start moving along the knot, as we encounter the crossings we
start numbering them, so every crossing has two numbers assigned to
it once we have traced the entire knot. Now we take the even number
associated with every crossing.
The following sign convention is to be followed:
Take the even number with a negative sign if it is an overcrossing
that we are encountering.
OUTPUT: DT code representation of the knot
EXAMPLES::
sage: K = Knot([[1,5,2,4],[5,3,6,2],[3,1,4,6]])
sage: K.dt_code()
[4, 6, 2]
sage: B = BraidGroup(4)
sage: K = Knot(B([1, 2, 1, 2]))
sage: K.dt_code()
[4, -6, 8, -2]
sage: K = Knot([[[1, -2, 3, -4, 5, -1, 2, -3, 4, -5]], [1, 1, 1, 1, 1]])
sage: K.dt_code()
[6, 8, 10, 2, 4]
"""
b = self.braid().Tietze()
N = len(b)
label = [0 for i in range(2 * N)]
string = 1
next_label = 1
type1 = 0
crossing = 0
while next_label <= 2 * N:
string_found = False
for i in range(crossing, N):
if abs(b[i]) == string or abs(b[i]) == string - 1:
string_found = True
crossing = i
break
if not string_found:
for i in range(0, crossing):
if abs(b[i]) == string or abs(b[i]) == string - 1:
string_found = True
crossing = i
break
assert label[2 * crossing + next_label % 2] != 1, "invalid knot"

label[2 * crossing + next_label % 2] = next_label
next_label = next_label + 1
if type1 == 0:
if b[crossing] < 0:
type1 = 1
else:
type1 = -1
else:
type1 = -1 * type1
if ((abs(b[crossing]) == string and b[crossing] * type1 > 0)
or (abs(b[crossing]) != string and b[crossing] * type1 < 0)):
if next_label % 2 == 1:
label[2 * crossing] = label[2 * crossing] * -1
if abs(b[crossing]) == string:
string = string + 1
else:
string = string - 1
crossing = crossing + 1
code = [0 for i in range(N)]
for i in range(N):
for j in range(N):
if label[2 * j + 1] == 2 * i + 1:
code[i] = label[2 * j]
break
return code

def arf_invariant(self):
"""
Return the Arf invariant.
EXAMPLES::
sage: B = BraidGroup(4)
sage: K = Knot(B([-1, 2, 1, 2]))
sage: K.arf_invariant()
0
sage: B = BraidGroup(8)
sage: K = Knot(B([-2, 3, 1, 2, 1, 4]))
sage: K.arf_invariant()
0
sage: K = Knot(B([1, 2, 1, 2]))
sage: K.arf_invariant()
1
"""
a = self.alexander_polynomial()
if Mod(a(-1), 8) == 1 or Mod(a(-1), 8) == 7:
return 0

return 1

0 comments on commit 84c522e

Please sign in to comment.