309 lines
12 KiB
Python
309 lines
12 KiB
Python
#!/usr/bin/env python
|
|
import collections
|
|
import sys
|
|
|
|
|
|
def mod_one(n):
|
|
"""This function returns the fractional part of some number."""
|
|
if n >= 1:
|
|
return mod_one(n - 1)
|
|
if n < 0:
|
|
return mod_one(n + 1)
|
|
return n
|
|
|
|
|
|
class av_signature_function(object):
|
|
'''
|
|
This simple class encodes twisted and untwisted signature functions
|
|
of knots. Since the signature function is entirely encoded by its signature
|
|
jump, the class stores only information about signature jumps
|
|
in a dictionary self.data.
|
|
The dictionary stores data of the signature jump as a key/values pair,
|
|
where the key is the argument at which the functions jumps
|
|
and value encodes the value of the jump. Remember that we treat
|
|
signature functions as defined on the interval [0,1).
|
|
'''
|
|
def __init__(self, values=[]):
|
|
# We will store data of signature jumps here.
|
|
self.data = collections.defaultdict(int)
|
|
# values contain initial data of singature jumps
|
|
for jump_arg, jump in values:
|
|
assert 0 <= jump_arg < 1, \
|
|
"Signature function is defined on the interval [0, 1)."
|
|
self.data[jump_arg] = jump
|
|
|
|
|
|
def value(self, arg):
|
|
# Compute the value of the signature function at the point arg.
|
|
# This requires summing all signature jumps that occur before arg.
|
|
assert 0 <= arg < 1, \
|
|
"Signature function is defined on the interval [0, 1)."
|
|
val = 0
|
|
for jump_arg, jump in self.data.items():
|
|
if jump_arg < arg:
|
|
val += 2 * jump
|
|
elif jump_arg == arg:
|
|
val += jump
|
|
return val
|
|
|
|
def total_sign_jump(self):
|
|
# Total signature jump is the sum of all jumps.
|
|
a = sum([j[1] for j in self.to_list()])
|
|
b = sum(self.data.values())
|
|
# print b
|
|
assert a == b
|
|
return sum(self.data.values())
|
|
|
|
def total_absolute_sign_jump(self):
|
|
# Total signature jump is the sum of all jumps.
|
|
a = sum([abs(j[1]) for j in self.to_list()])
|
|
# b = sum(self.data.values())
|
|
# print b
|
|
# assert a == b
|
|
return a
|
|
|
|
|
|
def double_cover(self):
|
|
new_data = []
|
|
for jump_arg, jump in self.data.items():
|
|
new_data.append((mod_one(jump_arg/2), jump))
|
|
new_data.append((mod_one(1/2 + jump_arg/2), jump))
|
|
return av_signature_function(new_data)
|
|
|
|
|
|
def to_list(self):
|
|
# Return signature jumps formated as a list
|
|
return sorted(self.data.items(), key=lambda x: x[0])
|
|
|
|
def step_function_data(self):
|
|
# Transform the signature jump data to a format understandable
|
|
# by the plot function.
|
|
l = self.to_list()
|
|
vals = ([(d[0], sum(2 * j[1] for j in l[:l.index(d)+1])) for d in l] +
|
|
[(0, self.data[0]), (1, self.total_sign_jump())])
|
|
return vals
|
|
|
|
def plot(self):
|
|
# plot the signture function
|
|
plot_step_function(self.step_function_data())
|
|
|
|
def tikz_plot(self, file_name):
|
|
# Draw the graph of the signature and transform it into TiKz.
|
|
# header of the LaTeX file
|
|
output_file = open(file_name, "w")
|
|
output_file.write("\\documentclass[tikz]{standalone}\n")
|
|
output_file.write("\\usetikzlibrary{datavisualization,datavisualization.formats.functions}\n")
|
|
output_file.write("\\begin{document}\n")
|
|
output_file.write("\\begin{tikzpicture}\n")
|
|
data = sorted(self.step_function_data())
|
|
output_file.write(" \\datavisualization[scientific axes,visualize as smooth line,\n")
|
|
output_file.write(" x axis={ticks={none,major={at={")
|
|
output_file.write(", " + str(N(data[0][0], digits=4)) + " as \\(" + str(data[0][0]) + "\\)")
|
|
for jump_arg, jump in data[1:]:
|
|
output_file.write(", " + str(N(jump_arg, digits=4)) + " as \\(" + str(jump_arg) + "\\)")
|
|
output_file.write("}}}}\n")
|
|
output_file.write(" ]\n")
|
|
output_file.write("data [format=function]{\n")
|
|
output_file.write("var x : interval [0:1];\n")
|
|
output_file.write("func y = \\value x;\n")
|
|
output_file.write("};\n")
|
|
# close LaTeX enviroments
|
|
output_file.write("\\end{tikzpicture}\n")
|
|
output_file.write("\\end{document}\n")
|
|
output_file.close()
|
|
|
|
def __lshift__(self, shift):
|
|
# Shift of the signature functions correspond to the rotations.
|
|
return self.__rshift__(-shift)
|
|
|
|
def __rshift__(self, shift):
|
|
new_data = []
|
|
for jump_arg, jump in self.data.items():
|
|
new_data.append((mod_one(jump_arg + shift), jump))
|
|
return av_signature_function(new_data)
|
|
|
|
def __sub__(self, other):
|
|
# we cn perform arithmetic operations on signature functions.
|
|
return self + other.__neg__()
|
|
|
|
def __neg__(self):
|
|
for jump_arg in self.data.keys():
|
|
self.data[jump_arg] *= -1
|
|
return self
|
|
|
|
def __add__(self, other):
|
|
new_one = av_signature_function()
|
|
new_data = collections.defaultdict(int)
|
|
for jump_arg, jump in other.data.items():
|
|
new_data[jump_arg] = jump + self.data.get(jump_arg, 0)
|
|
try:
|
|
int(jump_arg)
|
|
except:
|
|
print jump_arg
|
|
for jump_arg, jump in self.data.items():
|
|
if jump_arg not in new_data.keys():
|
|
new_data[jump_arg] = self.data[jump_arg]
|
|
|
|
new_one.data = new_data
|
|
return new_one
|
|
|
|
def __str__(self):
|
|
return '\n'.join([str(jump_arg) + ": " + str(jump)
|
|
for jump_arg, jump in sorted(self.data.items())])
|
|
|
|
def __repr__(self):
|
|
return self.__str__()
|
|
|
|
# 9.8
|
|
# ksi = exp( (2 PI * i) / (2k + 1))
|
|
# blanchfield = lambda_even + lambda_odd
|
|
|
|
def get_twisted_signature_function(k_n, theta):
|
|
results = []
|
|
k = abs(k_n)
|
|
|
|
ksi = 1/(2 * k + 1)
|
|
# lambda_odd (theta + e) % 2 == 0:
|
|
for e in range(1, k + 1):
|
|
if (theta + e) % 2 != 0:
|
|
results.append((e * ksi, 1 * sgn(k_n)))
|
|
results.append((1 - e * ksi, -1 * sgn(k_n)))
|
|
# lambda_even
|
|
# print "normal"
|
|
for e in range(1, theta):
|
|
if (theta + e) % 2 == 0:
|
|
# print e * ksi, ": 1"
|
|
# print 1 - e * ksi, ": -1 "
|
|
results.append((e * ksi, 1 * sgn(k_n)))
|
|
results.append((1 - e * ksi, -1 * sgn(k_n)))
|
|
|
|
# print "reversed"
|
|
for e in range(theta + 1, k + 1):
|
|
if (theta + e) % 2 != 0:
|
|
continue
|
|
# print e * ksi, ": -1"
|
|
# print 1 - e * ksi, ": 1 "
|
|
results.append((e * ksi, -1 * sgn(k_n)))
|
|
results.append((1 - e * ksi, 1 * sgn(k_n)))
|
|
return av_signature_function(results)
|
|
|
|
def get_blanchfield(t, k):
|
|
p = 2
|
|
q = 2 * k + 1
|
|
sigma_set = get_sigma_set(p, q)
|
|
sigma = len(sigma_set) - 2 * len([z for z in sigma_set if t < z < 1 + t])
|
|
return sigma
|
|
|
|
def get_sigma_set(p, q):
|
|
sigma_set = set()
|
|
for i in range(1, p):
|
|
for j in range(1, q):
|
|
sigma_set.add(j/q + i/p)
|
|
return sigma_set
|
|
|
|
# Bl_theta(K'_(2, d) = Bl_theta(T_2, d) + Bl(K')(ksi_l^(-theta) * t) + Bl(K')(ksi_l^theta * t)
|
|
|
|
def get_cable_signature_as_theta_function(*arg):
|
|
if len(arg) < 2:
|
|
print "It is not a cable"
|
|
return None
|
|
def signture_function(theta):
|
|
if theta > abs(arg[-1]):
|
|
print "k for pattern is " + str(arg[-1])
|
|
print "theta shouldn't be larger than this"
|
|
return None
|
|
if theta == 0:
|
|
cable_signature = get_untwisted_signutere_function(arg[-1])
|
|
else:
|
|
cable_signature = get_twisted_signature_function(arg[-1], theta)
|
|
|
|
for i, k_i in enumerate(arg[:-1][::-1]):
|
|
k = abs(k_i)
|
|
ksi = 1/(2 * k + 1)
|
|
power = 2^i
|
|
a = get_untwisted_signutere_function(k_i)
|
|
shift = theta * ksi * power
|
|
b = a >> shift
|
|
c = a << shift
|
|
for _ in range(i):
|
|
b = b.double_cover()
|
|
c = c.double_cover()
|
|
b += c
|
|
cable_signature += b
|
|
return cable_signature
|
|
return signture_function
|
|
|
|
|
|
|
|
def get_untwisted_signutere_function(*arg):
|
|
signture_function = av_signature_function([(0, 0)])
|
|
for k_i in arg:
|
|
k = abs(k_i)
|
|
# Return the signature function of the T_{2,2k+1} torus knot.
|
|
l = ([((2 * a + 1)/(4 * k + 2), -1 * sgn(k_i)) for a in range(k)] +
|
|
[((2 * a + 1)/(4 * k + 2), 1 * sgn(k_i)) for a in range(k + 1, 2 * k + 1)])
|
|
signture_function += av_signature_function(l)
|
|
return signture_function
|
|
|
|
def get_function_of_theta_for_sum(*arg):
|
|
def signture_function_for_sum(*thetas):
|
|
if len(thetas) != len(arg) - 1:
|
|
print "For each cable one theta value should be given"
|
|
return None
|
|
signature_function = get_untwisted_signutere_function(*arg[0])
|
|
for i, knot in enumerate(arg[1:]):
|
|
signature_function += (get_cable_signature_as_theta_function(*knot))(thetas[i])
|
|
return signature_function
|
|
return signture_function_for_sum
|
|
|
|
|
|
def tmp(limit=None):
|
|
if limit is None:
|
|
limit = 10
|
|
for k_0 in range(1, limit):
|
|
for k_1 in range(1, limit):
|
|
for k_2 in range(1, limit):
|
|
for k_3 in range(1, limit):
|
|
F = get_function_of_theta_for_sum([k_3, -k_2], [-k_0, -k_1, -k_3], [k_0, k_1, k_2])
|
|
for theta_0 in range(k_3 + 1):
|
|
for theta_1 in range(k_2 + 1):
|
|
f = F(theta_0, theta_1)
|
|
if f.total_absolute_sign_jump() != 0 and theta_1 + theta_0 == 0:
|
|
print 4 * "\n"
|
|
print "OJOJOJOJJOOJJOJJ!!!!!!!!!!"
|
|
print k_0, k_1, k_2, k_3
|
|
print theta_0, theta_1
|
|
|
|
if f.total_absolute_sign_jump() == 0 and theta_1 + theta_0 != 0:
|
|
# print "HURA"
|
|
# print k_0, k_1, k_2, k_3
|
|
# print theta_0, theta_1
|
|
if k_2 != k_3 or theta_0 != theta_1:
|
|
print 4 * "\n"
|
|
print " SUPER!!!!!!!!!!"
|
|
print k_0, k_1, k_2, k_3
|
|
print theta_0, theta_1
|
|
|
|
for k_4 in range(1, limit):
|
|
F = get_function_of_theta_for_sum([], [k_0, k_1, k_2], [k_3, k_4], [-k_0, -k_3, -k_4], [-k_1, -k_2])
|
|
for theta_0 in range(k_2 + 1):
|
|
for theta_1 in range(k_4 + 1):
|
|
for theta_2 in range(k_4 + 1):
|
|
for theta_3 in range(k_2 + 1):
|
|
f = F(theta_0, theta_1, theta_2, theta_3)
|
|
if f.total_absolute_sign_jump() != 0 and theta_1 + theta_0 + theta_3 + theta_2 == 0:
|
|
print 4 * "\n"
|
|
print "2 OJOJOJOJJOOJJOJJ!!!!!!!!!!"
|
|
print k_0, k_1, k_2, k_3, k_4
|
|
print theta_0, theta_1, theta_2, theta_3
|
|
|
|
if f.total_absolute_sign_jump() == 0 and theta_1 + theta_0 + theta_3 + theta_2 != 0:
|
|
# print "HURA"
|
|
# print k_0, k_1, k_2, k_3
|
|
# print theta_0, theta_1
|
|
if k_2 != k_3 or theta_0 != theta_1:
|
|
print 4 * "\n"
|
|
print "2 SUPER!!!!!!!!!!"
|
|
print k_0, k_1, k_2, k_3, k_4
|
|
print theta_0, theta_1, theta_2, theta_3
|