Skip to content

Commit e32bd82

Browse files
Link.alexander now handles inputs with R1 and R2 simplifications
1 parent cd29c62 commit e32bd82

File tree

5 files changed

+68
-11
lines changed

5 files changed

+68
-11
lines changed

spherogram_src/links/alexander.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,28 @@ def good_exhaustion(link, max_failed_tries=20):
249249
return E_best
250250

251251

252+
252253
def alexander(K):
254+
"""
255+
This function assumes no Type I moves is available.
256+
257+
Make sure the method that calls this gracefully handle inputs
258+
where such moves are present.
259+
260+
>>> from .invariants import Link
261+
>>> Link([(1, 4, 2, 1), (2, 4, 3, 3)]).alexander_polynomial()
262+
1
263+
>>> L = Link('K3a1')
264+
>>> L.unlinked_unknot_components = 1
265+
>>> L.alexander_polynomial()
266+
0
267+
"""
253268
c = len(K.crossings)
254-
if c < 100:
269+
if c == 0:
270+
assert K.unlinked_unknot_components == 1
271+
R = PolynomialRing(ZZ, 't')
272+
return R(1)
273+
elif c < 100:
255274
E = Exhaustion(K)
256275
else:
257276
E = good_exhaustion(K, max(20, 0.15 * c))

spherogram_src/links/invariants.py

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -267,24 +267,43 @@ def alexander_polynomial(self, multivar=True, v='no', method='default',
267267
raise RuntimeError('the method "snappy" for '
268268
'alexander_polynomial requires SnapPy')
269269

270+
# We do any available Type I and II Reidemeister moves as the
271+
# functions we call assume that none are available.
272+
273+
from . import simplify
274+
if simplify.has_reidemeister_I_or_II(self):
275+
L = self.copy()
276+
L.simplify('basic')
277+
return L.alexander_polynomial(multivar=multivar, v=v, method=method,
278+
norm=norm, factored=factored)
279+
280+
# We have to deal with the special case of unknotted and
281+
# unlinked components.
282+
270283
comp = len(self.link_components)
271-
if comp < 2:
284+
nugatory = self.unlinked_unknot_components
285+
if comp + nugatory < 2:
272286
multivar = False
273287

288+
if multivar:
289+
L = LaurentPolynomialRing(QQ, [f't{i+1}' for i in range(comp + nugatory)])
290+
t = list(L.gens())
291+
else:
292+
L = LaurentPolynomialRing(QQ, 't')
293+
t = [L.gen()]
294+
R = L.polynomial_ring() if norm else L
295+
296+
if nugatory > 0:
297+
p = 1 if comp + nugatory == 1 else 0
298+
return R(p)
299+
274300
# If single variable, use the super-fast method of Bar-Natan.
275301
if comp == 1 and method == 'default' and norm:
276302
p = alexander.alexander(self)
277303
else: # Use a simple method based on the Wirtinger presentation.
278304
if method not in ['default', 'wirtinger']:
279305
raise ValueError("Available methods are 'default' and 'wirtinger'")
280306

281-
if multivar:
282-
L = LaurentPolynomialRing(QQ, [f't{i+1}' for i in range(comp)])
283-
t = list(L.gens())
284-
else:
285-
L = LaurentPolynomialRing(QQ, 't')
286-
t = [L.gen()]
287-
288307
M = self.alexander_matrix(mv=multivar)
289308
C = M[0]
290309
m = C.nrows()
@@ -297,7 +316,7 @@ def alexander_polynomial(self, multivar=True, v='no', method='default',
297316
subMatrix = C[0: k, 0: k]
298317
p = subMatrix.determinant()
299318
if p == 0:
300-
return 0
319+
return R(0)
301320
if multivar:
302321
t_i = M[1][-1]
303322
p = (p.factor()) / (t_i - 1)

spherogram_src/links/simplify.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,22 @@ def reidemeister_I_and_II(link, A):
140140
return eliminated, changed
141141

142142

143+
def has_reidemeister_I_or_II(link):
144+
"""
145+
Checks if a Reidemeister I or II move is available.
146+
"""
147+
for A in link.crossings:
148+
# Type I
149+
if A in [B for B, i in A.adjacent]:
150+
return True
151+
# Type II
152+
for a in range(4):
153+
(B, b), (C, c) = A.adjacent[a], A.adjacent[a + 1]
154+
if B == C and (b - 1) % 4 == c and (a + b) % 2 == 0:
155+
return True
156+
return False
157+
158+
143159
def basic_simplify(link, build_components=True, to_visit=None,
144160
force_build_components=False):
145161
"""

spherogram_src/test.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
import spherogram.links.morse
77
import spherogram.links.seifert
88
import spherogram.links.exhaust
9+
import spherogram.links.alexander
910
import spherogram.links.bridge_bound
1011
import spherogram.links.bands
1112
import spherogram.links.bands.merge_links
1213
import spherogram.links.bands.core
1314
import spherogram.links.bands.search
1415
import spherogram.links.bands.regression
1516

17+
1618
import spherogram.test_helper as test_helper
1719
import getopt
1820
import sys
@@ -31,6 +33,7 @@
3133
spherogram.links.random_links,
3234
spherogram.links.orthogonal,
3335
spherogram.links.simplify,
36+
spherogram.links.alexander,
3437
spherogram.links.bridge_bound,
3538
spherogram.links.invariants,
3639
spherogram.links.morse,

spherogram_src/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version = '2.4'
1+
version = '2.4.1a1'

0 commit comments

Comments
 (0)