diff --git a/my_signature.sage b/my_signature.sage index b27e2d1..b46eb6d 100644 --- a/my_signature.sage +++ b/my_signature.sage @@ -2,17 +2,39 @@ import collections import sys +import inspect +import pandas as pd +import itertools as it -def mod_one(n): - """This function returns the fractional part of some number.""" - n -= int(n) - if n < 0: - n += 1 - return n +class MySettings(object): + def __init__(self): + k = 0 + +def main(arg): + my_settings = MySettings() + try: + tests(int(arg[1])) + except: + tests() -class av_signature_function(object): + +def tests(limit=10): + for comb in it.combinations_with_replacement(range(1, limit + 1), 5): + knot_description, null_comb, all_comb = second_sum(*comb) + if null_comb^2 >= all_comb: + print "\n\nHURA!!" + print comb + print knot_description + print "Zero cases: " + str(null_comb) + print "All cases: " + str(all_comb) + # for comb in it.combinations_with_replacement(range(1, limit + 1), 4): + # print comb + # print first_sum(*comb) + + +class SignatureFunction(object): """ This simple class encodes twisted and untwisted signature functions of knots. Since the signature function is entirely encoded by its signature @@ -32,7 +54,6 @@ class av_signature_function(object): "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. @@ -46,15 +67,6 @@ class av_signature_function(object): val += jump return val - def sum_of_values(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 - assert a == 0 - return sum(self.data.values()) - def sum_of_absolute_values(self): return sum([abs(i) for i in self.data.values()]) @@ -63,49 +75,7 @@ class av_signature_function(object): 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.sum_of_values())]) - 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() + return SignatureFunction(new_data) def __lshift__(self, shift): # Shift of the signature functions correspond to the rotations. @@ -115,48 +85,43 @@ class av_signature_function(object): 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) + return SignatureFunction(new_data) def __sub__(self, other): - # we cn perform arithmetic operations on signature functions. + # we can 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 + new_data = [] + for jump_arg, jump in self.data.items(): + new_data.append(jump_arg, -jump) + return SignatureFunction(new_data) def __add__(self, other): - new_one = av_signature_function() + new_signature_function = SignatureFunction() 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 + new_signature_function.data = new_data + return new_signature_function 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__() + # 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): +# Proposition 9.8. +def get_blanchfield_for_pattern(k_n, theta): + if theta == 0: + return get_untwisted_signature_function(k_n) results = [] k = abs(k_n) - ksi = 1/(2 * k + 1) # lambda_odd (theta + e) % 2 == 0: for e in range(1, k + 1): @@ -175,40 +140,39 @@ def get_twisted_signature_function(k_n, theta): continue results.append((e * ksi, -1 * sgn(k_n))) results.append((1 - e * ksi, 1 * sgn(k_n))) - return av_signature_function(results) + return SignatureFunction(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(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 -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) +# 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): 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) + cable_signature = get_blanchfield_for_pattern(arg[-1], theta) + for i, k in enumerate(arg[:-1][::-1]): + ksi = 1/(2 * abs(k) + 1) power = 2^i - a = get_untwisted_signutere_function(k_i) + a = get_untwisted_signature_function(k) shift = theta * ksi * power b = a >> shift c = a << shift @@ -220,102 +184,125 @@ def get_cable_signature_as_theta_function(*arg): 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_untwisted_signature_function(j): + # Return the signature function of the T_{2,2k+1} torus knot. + k = abs(j) + w = ([((2 * a + 1)/(4 * k + 2), -1 * sgn(j)) for a in range(k)] + + [((2 * a + 1)/(4 * k + 2), 1 * sgn(j)) + for a in range(k + 1, 2 * k + 1)]) + return SignatureFunction(w) + 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 + """ + Function intended to calculate signature function for a connected + sum of multiple cables with varying theta parameter values. + Accept arbitrary number of arguments (number of cables in connected sum). + Each argument should be given as list of integer representing + k - parameters for a cable: parameters k_i (i=1,.., n-1) for satelit knots + T(2, 2k_i + 1) and - the last one - k_n for a pattern knot T(2, 2k_n + 1). + Returns a function described below. + """ + def signature_function_for_sum(*thetas): + # Returns object of SignatureFunction class for a previously defined + # connercted sum of len(arg) cables. + # Accept len(arg) arguments: for each cable one theta parameter. + # If call with no arguments, all theta parameters are set to be 0. + la = len(arg) + lt = len(thetas) + if lt == 0: + return signature_function_for_sum(*(la * [0])) + if lt != la: + msg = "This function takes exactly " + str(la) + \ + " arguments or no argument at all (" + str(lt) + " given)." + raise TypeError(msg) + sf = SignatureFunction([(0, 0)]) + for i, knot in enumerate(arg): + sf += (get_cable_signature_as_theta_function(*knot))(thetas[i]) + return sf + return signature_function_for_sum -def first_sum(k_0, k_1, k_2, k_3): - 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) - f.sum_of_values() - if f.sum_of_absolute_values() != 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.sum_of_absolute_values() == 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 +def mod_one(n): + """This function returns the fractional part of some number.""" + return n - floor(n) -def second_sum(k_0, k_1, k_2, k_3, k_4): - 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.sum_of_absolute_values() != 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.sum_of_absolute_values() == 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 +# ###################### TEMPORARY TESTS ######### -def third_sum(k_0, k_1, k_2, k_3, k_4, k_5, k_6, k_7, k_8): - F = get_function_of_theta_for_sum([], [k_0, k_1, k_2], [k_3, k_4], [-k_5, -k_6, -k_7], [-k_8, -k_8]) - 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.sum_of_absolute_values() != 0 and theta_1 + theta_0 + theta_3 + theta_2 == 0: - print 4 * "\n" - print "3 OJOJOJOJJOOJJOJJ!!!!!!!!!!" - print k_0, k_1, k_2, k_3, k_4 - print theta_0, theta_1, theta_2, theta_3 +# def first_sum(*arg): +# k_0, k_1, k_2, k_3 = arg +# F = get_function_of_theta_for_sum([k_3], [-k_2], +# [-k_0, -k_1, -k_3], +# [k_0, k_1, k_2]) +# all_combinations = (k_3 + 1) * (k_2 + 1) * (k_3 + 1) * (k_2 + 1) +# null_combinations = 0 +# non_trivial_zeros = 0 +# for v_theta in it.product(range(k_3 + 1), range(k_2 + 1), +# range(k_3 + 1), range(k_2 + 1)): +# f = F(*v_theta) +# if f.sum_of_absolute_values() != 0 and sum(v_theta) == 0: +# print 4 * "\n" + "something wrong!!!!!!!!!!" +# print inspect.stack()[0][3] +# print arg +# print v_theta +# +# if f.sum_of_absolute_values() == 0: +# null_combinations += 1 +# if sum(v_theta) != 0: +# if len(arg) == len(set(arg)) and len(set(v_theta)) > 1: +# non_trivial_zeros += 1 +# # print "\nNontrivial zero" +# # print inspect.stack()[0][3] +# print arg +# print v_theta +# print +# return non_trivial_zeros, null_combinations, all_combinations - if f.sum_of_absolute_values() == 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 "3 SUPER!!!!!!!!!!" - print k_0, k_1, k_2, k_3, k_4 - print theta_0, theta_1, theta_2, theta_3 -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): - first_sum(k_0, k_1, k_2, k_3) - for k_4 in range(1, limit): - second_sum(k_0, k_1, k_2, k_3, k_4) +def get_knot_descrption(*arg): + description = "" + for knot in arg: + if knot[0] < 0: + description += "-" + description += "T(" + for k in knot: + description += "2, " + str(abs(k)) + "; " + description = description[:-2] + description += ") # " + return description[:-3] + +def get_number_of_combinations(*arg): + number_of_combinations = 1 + for knot in arg: + number_of_combinations *= (2 * knot[-1] + 1) + return number_of_combinations + +def second_sum(*arg): + k_0, k_1, k_2, k_3, k_4 = arg + knot_sum = [[k_0, k_1, k_2], [k_3, k_4], [-k_0, -k_3, -k_4], [-k_1, -k_2]] + F = get_function_of_theta_for_sum(*knot_sum) + knot_description = get_knot_descrption(*knot_sum) + all_combinations = get_number_of_combinations(*knot_sum) + null_combinations = 1 + # non_trivial_zeros = 0 + + for v_theta in it.product(range(k_2 + 1), range(k_4 + 1), + range(k_4 + 1), range(k_2 + 1)): + f = F(*v_theta) + assert f.sum_of_absolute_values() == 0 or sum(v_theta) != 0 + if f.sum_of_absolute_values() == 0 and sum(v_theta) != 0: + null_combinations += 2 + # if len(arg) == len(set(arg)) and len(set(v_theta)) > 1: + # non_trivial_zeros += 1 + # print "\nNontrivial zero" + # print inspect.stack()[0][3] + # print arg + # print v_theta + # print + return knot_description, null_combinations, all_combinations + + +if __name__ == '__main__' and '__file__' in globals(): + main(sys.argv)