From d9986b63c1adadfa6626d6c5bdde0e7d75bda098 Mon Sep 17 00:00:00 2001 From: Maria Marchwicka Date: Mon, 31 Aug 2020 18:12:47 +0200 Subject: [PATCH] classes as separate module - now working --- cable_signature.sage | 291 ++++++++++++++++++++++++++++++++++++++++++- my_signature.sage | 291 ++++--------------------------------------- 2 files changed, 312 insertions(+), 270 deletions(-) diff --git a/cable_signature.sage b/cable_signature.sage index 44f4b64..4c547a0 100644 --- a/cable_signature.sage +++ b/cable_signature.sage @@ -1,6 +1,8 @@ #!/usr/bin/python import collections - +import numpy as np +import itertools as it +import re class TorusCable(object): def __init__(self, knot_formula, k_vector=None, q_vector=None): @@ -514,3 +516,290 @@ class SignatureFunction(object): def mod_one(n): return n - floor(n) + +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(values=w) + + +def get_signature_summand_as_theta_function(*arg): + def get_signture_function(theta): + # TBD: another formula (for t^2) description + + k_n = abs(arg[-1]) + if theta > k_n: + msg = "k for the pattern in the cable is " + str(arg[-1]) + \ + ". Parameter theta should not be larger than abs(k)." + raise ValueError(msg) + + # twisted part + cable_signature = get_blanchfield_for_pattern(arg[-1], theta) + + # untwisted part + for i, k in enumerate(arg[:-1][::-1]): + ksi = 1/(2 * k_n + 1) + power = 2^i + a = get_untwisted_signature_function(k) + shift = theta * ksi * power + b = a >> shift + c = a << shift + for _ in range(i): + b = b.double_cover() + c = c.double_cover() + cable_signature += b + c + test = b - c + test2 = -c + b + assert test == test + return cable_signature + get_signture_function.__doc__ = get_signture_function_docsting + return get_signture_function + + +def get_blanchfield_for_pattern(k_n, theta): + if theta == 0: + a = get_untwisted_signature_function(k_n) + return a.square_root() + a.minus_square_root() + + results = [] + k = abs(k_n) + ksi = 1/(2 * k + 1) + + # lambda_odd, i.e. (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: + 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 + results.append((e * ksi, -1 * sgn(k_n))) + results.append((1 - e * ksi, 1 * sgn(k_n))) + return SignatureFunction(values=results) + + +def get_signature_summand_as_theta_function(*arg): + def get_signture_function(theta): + # TBD: another formula (for t^2) description + + k_n = abs(arg[-1]) + if theta > k_n: + msg = "k for the pattern in the cable is " + str(arg[-1]) + \ + ". Parameter theta should not be larger than abs(k)." + raise ValueError(msg) + + # twisted part + cable_signature = get_blanchfield_for_pattern(arg[-1], theta) + + # untwisted part + for i, k in enumerate(arg[:-1][::-1]): + ksi = 1/(2 * k_n + 1) + power = 2^i + a = get_untwisted_signature_function(k) + shift = theta * ksi * power + b = a >> shift + c = a << shift + for _ in range(i): + b = b.double_cover() + c = c.double_cover() + cable_signature += b + c + test = b - c + test2 = -c + b + assert test == test + return cable_signature + get_signture_function.__doc__ = get_signture_function_docsting + return get_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(values=w) + + +TorusCable.get_number_of_combinations_of_theta.__doc__ = \ + """ + Arguments: + arbitrary number of lists of numbers, each list encodes a single cable + Return: + number of possible theta values combinations that could be applied + for a given cable sum, + i.e. the product of q_j for j = {1,.. n}, + where n is a number of direct components in the cable sum, + and q_j is the last q parameter for the component (a single cable) + """ + +TorusCable.get_knot_descrption.__doc__ = \ + """ + Arguments: + arbitrary number of lists of numbers, each list encodes a single cable. + Examples: + sage: get_knot_descrption([1, 3], [2], [-1, -2], [-3]) + 'T(2, 3; 2, 7) # T(2, 5) # -T(2, 3; 2, 5) # -T(2, 7)' + """ + +TorusCable.eval_cable_for_null_signature.__doc__ = \ + """ + This function calculates all possible twisted signature functions for + a knot that is given as an argument. The knot should be encoded as a list + of its direct component. Each component schould be presented as a list + of integers. This integers correspond to the k - values in each component/ + cable. If a component is a mirror image of a cable the minus sign should + be written before each number for this component. For example: + eval_cable_for_null_signature([[1, 8], [2], [-2, -8], [-2]]) + eval_cable_for_null_signature([[1, 2], [-1, -2]]) + + sage: eval_cable_for_null_signature([[1, 3], [2], [-1, -2], [-3]]) + + T(2, 3; 2, 7) # T(2, 5) # -T(2, 3; 2, 5) # -T(2, 7) + Zero cases: 1 + All cases: 1225 + Zero theta combinations: + (0, 0, 0, 0) + + sage: + The numbers given to the function eval_cable_for_null_signature + are k-values for each component/cable in a direct sum. + """ + +TorusCable.get_signature_as_function_of_theta.__doc__ = \ + """ + Function intended to construct signature function for a connected + sum of multiple cables with varying theta parameter values. + Accept arbitrary number of arguments (depending on 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 that will take theta vector as an argument and return + an object SignatureFunction. + + To calculate signature function for a cable sum and a theta values vector, + use as below. + + sage: signature_function_generator = get_signature_as_function_of_theta( + [1, 3], [2], [-1, -2], [-3]) + sage: sf = signature_function_generator(2, 1, 2, 2) + sage: print(sf) + 0: 0 + 5/42: 1 + 1/7: 0 + 1/5: -1 + 7/30: -1 + 2/5: 1 + 3/7: 0 + 13/30: -1 + 19/42: -1 + 23/42: 1 + 17/30: 1 + 4/7: 0 + 3/5: -1 + 23/30: 1 + 4/5: 1 + 6/7: 0 + 37/42: -1 + + Or like below. + sage: print(get_signature_as_function_of_theta([1, 3], [2], [-1, -2], [-3] + )(2, 1, 2, 2)) + 0: 0 + 1/7: 0 + 1/6: 0 + 1/5: -1 + 2/5: 1 + 3/7: 0 + 1/2: 0 + 4/7: 0 + 3/5: -1 + 4/5: 1 + 5/6: 0 + 6/7: 0 + """ + +SignatureFunction.__doc__ = \ + """ + 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.cnt_signature_jumps. + 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). + """ + +get_signture_function_docsting = \ + """ + This function returns SignatureFunction for previously defined single + cable T_(2, q) and a theta given as an argument. + The cable was defined by calling function + get_signature_summand_as_theta_function(*arg) + with the cable description as an argument. + It is an implementaion of the formula: + Bl_theta(K'_(2, d)) = + Bl_theta(T_2, d) + Bl(K')(ksi_l^(-theta) * t) + + Bl(K')(ksi_l^theta * t) + """ + +signature_as_function_of_theta_docstring = \ + """ + Arguments: + + Returns object of SignatureFunction class for a previously defined + connected 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. + """ + +mod_one.__doc__ = \ + """ + Argument: + a number + Return: + the fractional part of the argument + Examples: + sage: mod_one(9 + 3/4) + 3/4 + sage: mod_one(-9 + 3/4) + 3/4 + sage: mod_one(-3/4) + 1/4 + """ + +get_blanchfield_for_pattern.__doc__ = \ + """ + Arguments: + k_n: a number s.t. q_n = 2 * k_n + 1, where + T(2, q_n) is a pattern knot for a single cable from a cable sum + theta: twist/character for the cable (value form v vector) + Return: + SignatureFunction created for twisted signature function + for a given cable and theta/character + Based on: + Proposition 9.8. in Twisted Blanchfield Pairing + (https://arxiv.org/pdf/1809.08791.pdf) + """ + +get_signature_summand_as_theta_function.__doc__ = \ + """ + Argument: + n integers that encode a single cable, i.e. + values of q_i for T(2,q_0; 2,q_1; ... 2, q_n) + Return: + a function that returns SignatureFunction for this single cable + and a theta given as an argument + """ diff --git a/my_signature.sage b/my_signature.sage index 11a2344..138e514 100644 --- a/my_signature.sage +++ b/my_signature.sage @@ -11,6 +11,11 @@ import collections import itertools as it import numpy as np import re +# try: +# from cable_signature import SignatureFunction, TorusCable +# except ModuleNotFoundError: +os.system('sage --preparse cable_signature.sage') +os.system('mv cable_signature.sage.py cable_signature.py') from cable_signature import SignatureFunction, TorusCable class Config(object): @@ -189,7 +194,7 @@ def search_for_null_signature_value(knot_formula=None, limit=None): for k in combinations: if config.only_slice_candidates and k_vector_size == 5: k = get_shifted_combination(k) - cable = TorusCable(knot_formula, k_vector=k) + cable = TorusCable(knot_formula, k_vector=k) if is_trivial_combination(cable.knot_sum): print(cable.knot_sum) continue @@ -201,6 +206,11 @@ def search_for_null_signature_value(knot_formula=None, limit=None): str(all_comb) + "\n") f_results.write(line) +def extract_max(string): + numbers = re.findall('\d+', string) + numbers = map(int, numbers) + return max(numbers) + def is_trivial_combination(knot_sum): # for now is applicable only for schema that are sums of 4 cables if len(knot_sum) == 4: @@ -209,144 +219,6 @@ def is_trivial_combination(knot_sum): return True return False -def get_shifted_combination(combination): - # for now applicable only for schama - # "[[k[0], k[1], k[2]], [k[3], k[4]], - # [-k[0], -k[3], -k[4]], [-k[1], -k[2]]]" - # shift the combination so that the knot can be a candidate for slice - combination = [combination[0], 4 * combination[0] + combination[1], - 4 * (4 * combination[0] + combination[1]) + combination[2], - 4 * combination[0] + combination[3], - 4 * (4 * combination[0] + combination[3]) + combination[4]] - return combination - -def get_blanchfield_for_pattern(k_n, theta): - if theta == 0: - a = get_untwisted_signature_function(k_n) - return a.square_root() + a.minus_square_root() - - results = [] - k = abs(k_n) - ksi = 1/(2 * k + 1) - - # lambda_odd, i.e. (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: - 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 - results.append((e * ksi, -1 * sgn(k_n))) - results.append((1 - e * ksi, 1 * sgn(k_n))) - return SignatureFunction(values=results) - -def get_signature_summand_as_theta_function(*arg): - def get_signture_function(theta): - # TBD: another formula (for t^2) description - - k_n = abs(arg[-1]) - if theta > k_n: - msg = "k for the pattern in the cable is " + str(arg[-1]) + \ - ". Parameter theta should not be larger than abs(k)." - raise ValueError(msg) - - # twisted part - cable_signature = get_blanchfield_for_pattern(arg[-1], theta) - - # untwisted part - for i, k in enumerate(arg[:-1][::-1]): - ksi = 1/(2 * k_n + 1) - power = 2^i - a = get_untwisted_signature_function(k) - shift = theta * ksi * power - b = a >> shift - c = a << shift - for _ in range(i): - b = b.double_cover() - c = c.double_cover() - cable_signature += b + c - test = b - c - test2 = -c + b - assert test == test - return cable_signature - get_signture_function.__doc__ = get_signture_function_docsting - return get_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(values=w) - -def extract_max(string): - numbers = re.findall('\d+', string) - numbers = map(int, numbers) - return max(numbers) - -def mod_one(n): - return n - floor(n) - - -get_blanchfield_for_pattern.__doc__ = \ - """ - Arguments: - k_n: a number s.t. q_n = 2 * k_n + 1, where - T(2, q_n) is a pattern knot for a single cable from a cable sum - theta: twist/character for the cable (value form v vector) - Return: - SignatureFunction created for twisted signature function - for a given cable and theta/character - Based on: - Proposition 9.8. in Twisted Blanchfield Pairing - (https://arxiv.org/pdf/1809.08791.pdf) - """ - -TorusCable.get_number_of_combinations_of_theta.__doc__ = \ - """ - Arguments: - arbitrary number of lists of numbers, each list encodes a single cable - Return: - number of possible theta values combinations that could be applied - for a given cable sum, - i.e. the product of q_j for j = {1,.. n}, - where n is a number of direct components in the cable sum, - and q_j is the last q parameter for the component (a single cable) - """ - -TorusCable.get_knot_descrption.__doc__ = \ - """ - Arguments: - arbitrary number of lists of numbers, each list encodes a single cable. - Examples: - sage: get_knot_descrption([1, 3], [2], [-1, -2], [-3]) - 'T(2, 3; 2, 7) # T(2, 5) # -T(2, 3; 2, 5) # -T(2, 7)' - """ - -mod_one.__doc__ = \ - """ - Argument: - a number - Return: - the fractional part of the argument - Examples: - sage: mod_one(9 + 3/4) - 3/4 - sage: mod_one(-9 + 3/4) - 3/4 - sage: mod_one(-3/4) - 1/4 - """ search_for_null_signature_value.__doc__ = \ """ @@ -367,6 +239,17 @@ search_for_null_signature_value.__doc__ = \ Data for knots that are candidates for slice knots are saved to a file. """ +main.__doc__ = \ + """ + This function is run if the script was called from the terminal. + It calls another function, search_for_null_signature_value, + to calculate signature functions for a schema + of a cable sum defined in the class Config. + Optionaly a parameter (a limit for k_0 value) can be given. + Thought to be run for time consuming calculations. + """ + + extract_max.__doc__ = \ """ Return: @@ -378,136 +261,6 @@ extract_max.__doc__ = \ 3300 """ -TorusCable.eval_cable_for_null_signature.__doc__ = \ - """ - This function calculates all possible twisted signature functions for - a knot that is given as an argument. The knot should be encoded as a list - of its direct component. Each component schould be presented as a list - of integers. This integers correspond to the k - values in each component/ - cable. If a component is a mirror image of a cable the minus sign should - be written before each number for this component. For example: - eval_cable_for_null_signature([[1, 8], [2], [-2, -8], [-2]]) - eval_cable_for_null_signature([[1, 2], [-1, -2]]) - - sage: eval_cable_for_null_signature([[1, 3], [2], [-1, -2], [-3]]) - - T(2, 3; 2, 7) # T(2, 5) # -T(2, 3; 2, 5) # -T(2, 7) - Zero cases: 1 - All cases: 1225 - Zero theta combinations: - (0, 0, 0, 0) - - sage: - The numbers given to the function eval_cable_for_null_signature - are k-values for each component/cable in a direct sum. - """ - -TorusCable.get_signature_as_function_of_theta.__doc__ = \ - """ - Function intended to construct signature function for a connected - sum of multiple cables with varying theta parameter values. - Accept arbitrary number of arguments (depending on 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 that will take theta vector as an argument and return - an object SignatureFunction. - - To calculate signature function for a cable sum and a theta values vector, - use as below. - - sage: signature_function_generator = get_signature_as_function_of_theta( - [1, 3], [2], [-1, -2], [-3]) - sage: sf = signature_function_generator(2, 1, 2, 2) - sage: print(sf) - 0: 0 - 5/42: 1 - 1/7: 0 - 1/5: -1 - 7/30: -1 - 2/5: 1 - 3/7: 0 - 13/30: -1 - 19/42: -1 - 23/42: 1 - 17/30: 1 - 4/7: 0 - 3/5: -1 - 23/30: 1 - 4/5: 1 - 6/7: 0 - 37/42: -1 - - Or like below. - sage: print(get_signature_as_function_of_theta([1, 3], [2], [-1, -2], [-3] - )(2, 1, 2, 2)) - 0: 0 - 1/7: 0 - 1/6: 0 - 1/5: -1 - 2/5: 1 - 3/7: 0 - 1/2: 0 - 4/7: 0 - 3/5: -1 - 4/5: 1 - 5/6: 0 - 6/7: 0 - """ - -get_signature_summand_as_theta_function.__doc__ = \ - """ - Argument: - n integers that encode a single cable, i.e. - values of q_i for T(2,q_0; 2,q_1; ... 2, q_n) - Return: - a function that returns SignatureFunction for this single cable - and a theta given as an argument - """ -SignatureFunction.__doc__ = \ - """ - 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.cnt_signature_jumps. - 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). - """ -get_signture_function_docsting = \ - """ - This function returns SignatureFunction for previously defined single - cable T_(2, q) and a theta given as an argument. - The cable was defined by calling function - get_signature_summand_as_theta_function(*arg) - with the cable description as an argument. - It is an implementaion of the formula: - Bl_theta(K'_(2, d)) = - Bl_theta(T_2, d) + Bl(K')(ksi_l^(-theta) * t) - + Bl(K')(ksi_l^theta * t) - """ - -signature_as_function_of_theta_docstring = \ - """ - Arguments: - - Returns object of SignatureFunction class for a previously defined - connected 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. - """ - -main.__doc__ = \ - """ - This function is run if the script was called from the terminal. - It calls another function, search_for_null_signature_value, - to calculate signature functions for a schema - of a cable sum defined in the class Config. - Optionaly a parameter (a limit for k_0 value) can be given. - Thought to be run for time consuming calculations. - """ if __name__ == '__main__': global config