126 lines
4.6 KiB
Python
126 lines
4.6 KiB
Python
|
#!/usr/bin/env python
|
||
|
import collections
|
||
|
|
||
|
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)
|
||
|
else:
|
||
|
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 and jump_arg < 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 and arg < 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.
|
||
|
return sum([j[1] for j in self.to_list()])
|
||
|
|
||
|
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 signture functions correspond to the rotations.
|
||
|
return self.__rshift__(-shift)
|
||
|
|
||
|
def __rshift__(self, shift):
|
||
|
new_data = list()
|
||
|
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):
|
||
|
for jump_arg, jump in other.data.items():
|
||
|
self.data[jump_arg] += jump
|
||
|
return self
|
||
|
|
||
|
def __str__(self):
|
||
|
return '\n'.join([str(jump_arg) + ": " + str(jump)
|
||
|
for jump_arg, jump in self.data.items()])
|
||
|
|
||
|
def __repr__(self):
|
||
|
print self.__str__()
|
||
|
|
||
|
def untw_signature(k):
|
||
|
# Return the signture function of the T_{2,2k+1} torus knot.
|
||
|
l = ([((2 * a + 1)/(4 * k + 2), -1) for a in range(k)] +
|
||
|
[((2 * a + 1)/(4 * k + 2), 1) for a in range(k + 1, 2 * k + 1)])
|
||
|
return av_signature_function(l)
|