Skip to content

Commit e48fde6

Browse files
author
Release Manager
committed
gh-40081: Integration of a new optional package for Khovanov homology <!-- ^ Please provide a concise and informative title. --> <!-- ^ Don't put issue numbers in the title, do this in the PR description below. --> <!-- ^ For example, instead of "Fixes #12345" use "Introduce new method to calculate 1 + 2". --> <!-- v Describe your changes below in detail. --> <!-- v Why is this change required? What problem does it solve? --> <!-- v If this PR resolves an open issue, please link to it here. For example, "Fixes #12345". --> Sage has a native implementation of Khovanov homology. Unfortunately, it's not very performant. For knots and links with more than six crossings, the calculation takes more than a second on a ThinkPad with an i7 (i7-1165G7 @ 2.80GHz) processor (running Ubuntu under WSL2). For a knot with nine crossings, it takes more than a minute, and for 10 crossings, the calculation breaks (after about an hour) with a `Pari stack overflow`: ``` sage: K7 = Knots().from_table(7,1) ....: K8 = Knots().from_table(8,1) ....: K9 = Knots().from_table(9,1) ....: K10 = Knots().from_table(10,1) sage: %time K7.khovanov_homology() CPU times: user 679 ms, sys: 0 ns, total: 679 ms Wall time: 679 ms {-21: {-7: Z}, -19: {-7: 0, -6: C2}, -17: {-7: 0, -6: Z, -5: Z}, -15: {-7: 0, -6: 0, -5: 0, -4: C2}, -13: {-7: 0, -6: 0, -5: 0, -4: Z, -3: Z}, -11: {-7: 0, -6: 0, -5: 0, -4: 0, -3: 0, -2: C2}, -9: {-7: 0, -6: 0, -5: 0, -4: 0, -3: 0, -2: Z, -1: 0, 0: 0}, -7: {-7: 0, -6: 0, -5: 0, -4: 0, -3: 0, -2: 0, -1: 0, 0: Z}, -5: {0: Z}} sage: %time K8.khovanov_homology() CPU times: user 22.9 s, sys: 74.1 ms, total: 23 s Wall time: 23 s {-13: {-6: Z}, -11: {-6: 0, -5: C2, -4: 0, -3: 0}, -9: {-6: 0, -5: Z, -4: Z, -3: 0, -2: 0, -1: 0}, -7: {-6: 0, -5: 0, -4: 0, -3: Z x C2, -2: 0, -1: 0, 0: 0, 1: 0}, -5: {-6: 0, -5: 0, -4: 0, -3: Z, -2: Z x C2, -1: 0, 0: 0, 1: 0, 2: 0}, -3: {-6: 0, -5: 0, -4: 0, -3: 0, -2: Z, -1: Z x C2, 0: 0, 1: 0, 2: 0, 3: 0}, -1: {-4: 0, -3: 0, -2: 0, -1: Z, 0: Z x C2, 1: 0, 2: 0, 3: 0, 4: 0}, 1: {-3: 0, -2: 0, -1: 0, 0: Z x Z, 1: Z, 2: 0, 3: 0, 4: 0}, 3: {-1: 0, 0: 0, 1: 0, 2: C2, 3: 0, 4: 0}, 5: {1: 0, 2: Z, 3: 0, 4: 0}} sage: %time K9.khovanov_homology() CPU times: user 1min 23s, sys: 260 ms, total: 1min 23s Wall time: 1min 23s {-27: {-9: Z}, -25: {-9: 0, -8: C2}, -23: {-9: 0, -8: Z, -7: Z}, -21: {-9: 0, -8: 0, -7: 0, -6: C2}, -19: {-9: 0, -8: 0, -7: 0, -6: Z, -5: Z}, -17: {-9: 0, -8: 0, -7: 0, -6: 0, -5: 0, -4: C2}, -15: {-9: 0, -8: 0, -7: 0, -6: 0, -5: 0, -4: Z, -3: Z}, -13: {-9: 0, -8: 0, -7: 0, -6: 0, -5: 0, -4: 0, -3: 0, -2: C2}, -11: {-9: 0, -8: 0, -7: 0, -6: 0, -5: 0, -4: 0, -3: 0, -2: Z, -1: 0, 0: 0}, -9: {-9: 0, -8: 0, -7: 0, -6: 0, -5: 0, -4: 0, -3: 0, -2: 0, -1: 0, 0: Z}, -7: {0: Z}} sage: %time K10.khovanov_homology() Traceback (most recent call last): ... PariError: the PARI stack overflows (current size: 1073741824; maximum size: 1073741824) You can use pari.allocatemem() to change the stack size and try again ``` If we do the same with the optional package `Khoca` implemented in this PR, we get the following: The knot with 9 crossings takes less than half a second and the example with 10 crossings terminates after less than two seconds: ``` sage: %time K9.khovanov_homology(implementation='Khoca') CPU times: user 268 ms, sys: 44.7 ms, total: 313 ms Wall time: 293 ms {-27: {-9: Z}, -25: {-9: 0, -8: C2}, -23: {-9: 0, -8: Z, -7: Z}, -21: {-8: 0, -7: 0, -6: C2}, -19: {-7: 0, -6: Z, -5: Z}, -17: {-6: 0, -5: 0, -4: C2}, -15: {-5: 0, -4: Z, -3: Z}, -13: {-4: 0, -3: 0, -2: C2}, -11: {-3: 0, -2: Z}, -9: {0: Z}, -7: {0: Z}} sage: %time K10.khovanov_homology(implementation='Khoca') CPU times: user 1.55 s, sys: 123 ms, total: 1.68 s Wall time: 1.65 s {-17: {-8: Z}, -15: {-8: 0, -7: C2}, -13: {-8: 0, -7: Z, -6: Z}, -11: {-7: 0, -6: 0, -5: Z x C2}, -9: {-6: 0, -5: Z, -4: Z x C2}, -7: {-5: 0, -4: Z, -3: Z x C2}, -5: {-4: 0, -3: Z, -2: Z x C2}, -3: {-3: 0, -2: Z, -1: Z x C2}, -1: {-2: 0, -1: Z, 0: Z x C2}, 1: {-1: 0, 0: Z x Z, 1: Z}, 3: {0: 0, 1: 0, 2: C2}, 5: {1: 0, 2: Z}} ``` Even knots with 13 crossing only need a few seconds: ``` sage: K13 = KnotInfo.K13a_1.link() sage: %time K13.khovanov_homology(implementation='Khoca') CPU times: user 2.28 s, sys: 578 ms, total: 2.86 s Wall time: 2.6 s {-17: {-8: Z}, -15: {-8: 0, -7: Z x Z x Z x C2}, -13: {-8: 0, -7: Z, -6: Z^7 x C2 x C2 x C2}, -11: {-7: 0, -6: Z x Z x Z, -5: Z^13 x C2^7}, -9: {-6: 0, -5: Z^7, -4: Z^19 x C2^13}, -7: {-5: 0, -4: Z^13, -3: Z^24 x C2^19}, -5: {-4: 0, -3: Z^19, -2: Z^27 x C2^24}, -3: {-3: 0, -2: Z^24, -1: Z^25 x C2^27}, -1: {-2: 0, -1: Z^27, 0: Z^22 x C2^25}, 1: {-1: 0, 0: Z^26, 1: Z^16 x C2^21}, 3: {0: 0, 1: Z^21, 2: Z^9 x C2^16}, 5: {1: 0, 2: Z^16, 3: Z x Z x Z x Z x C2^9}, 7: {2: 0, 3: Z^9, 4: Z x C2 x C2 x C2 x C2}, 9: {3: 0, 4: Z x Z x Z x Z, 5: C2}, 11: {4: 0, 5: Z}} ``` The software behind the optional package is [Khoca](http://lewark.de/lukas/khoca.html). It was written in C++ by [Lukas Lewark](https://people.math.ethz.ch/~llewark/index.php). I packaged it on [PyPI](https://pypi.org/project/khoca/) for integration into Sage (see LLewark/khoca#3). Currently, there is still an issue with the PyPI package regarding integration with Sage, as both use the Pari library (see LLewark/khoca#3 (comment)). This occurs sporadically and triggers a system error that occurs at `cypari2/stack.pyx`. The error disappears when the last action is re- executed. I'm leaving this PR as a draft until the issue is resolved. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [x] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - #12345: short description why this is a dependency --> <!-- - #34567: ... --> URL: #40081 Reported by: Sebastian Oehms Reviewer(s): Sebastian Oehms, Travis Scrimshaw
2 parents efeb8f4 + 240e7ce commit e48fde6

File tree

13 files changed

+389
-8
lines changed

13 files changed

+389
-8
lines changed

build/pkgs/khoca/SPKG.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
khoca: Khoca as pip installable package
2+
=======================================
3+
4+
Description
5+
-----------
6+
7+
Khoca as pip installable package
8+
9+
License
10+
-------
11+
12+
GPLv2+
13+
14+
Upstream Contact
15+
----------------
16+
17+
https://pypi.org/project/khoca/
18+

build/pkgs/khoca/dependencies

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ipython cypari | $(PYTHON_TOOLCHAIN) sagelib $(PYTHON)
2+
3+
4+
----------
5+
All lines of this file are ignored except the first.

build/pkgs/khoca/package-version.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1.4

build/pkgs/khoca/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# See https://github.com/sagemath/sage/pull/40081
2+
khoca

build/pkgs/khoca/spkg-configure.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
SAGE_SPKG_CONFIGURE([khoca], [SAGE_PYTHON_PACKAGE_CHECK([khoca])])

build/pkgs/khoca/spkg-install.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cd src
2+
sdh_pip_install .

build/pkgs/khoca/type

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
optional
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
khoca

src/sage/features/khoca.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
r"""
2+
Check for Khoca
3+
"""
4+
from . import PythonModule
5+
6+
7+
class Khoca(PythonModule):
8+
r"""
9+
A :class:`sage.features.Feature` describing the presence of Khoca.
10+
11+
Khoca is provided by an optional package in the Sage distribution.
12+
13+
EXAMPLES::
14+
15+
sage: from sage.features.khoca import Khoca
16+
sage: Khoca().is_present() # optional - khoca
17+
FeatureTestResult('khoca', True)
18+
"""
19+
def __init__(self):
20+
r"""
21+
TESTS::
22+
23+
sage: from sage.features.khoca import Khoca
24+
sage: isinstance(Khoca(), Khoca)
25+
True
26+
"""
27+
PythonModule.__init__(self, 'khoca', spkg='khoca')
28+
29+
30+
def all_features():
31+
return [Khoca()]

src/sage/interfaces/all.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
lazy_import('sage.interfaces.gnuplot', 'gnuplot')
2424
lazy_import('sage.interfaces.gp', ['gp', 'gp_version', 'Gp'])
2525
lazy_import('sage.interfaces.kash', ['kash', 'kash_version', 'Kash'])
26+
lazy_import('sage.interfaces.khoca', ['khoca', 'Khoca'])
2627
lazy_import('sage.interfaces.lie', ['lie', 'LiE'])
2728
lazy_import('sage.interfaces.lisp', ['lisp', 'Lisp'])
2829
lazy_import('sage.interfaces.macaulay2', ['macaulay2', 'Macaulay2'])

0 commit comments

Comments
 (0)