add property in CableTorus

This commit is contained in:
Maria Marchwicka 2020-09-24 22:55:44 +02:00
parent acbf651697
commit c51064abf0

View File

@ -14,21 +14,20 @@ SIGMA = 1
class SignatureFunction(object): class SignatureFunction(object):
def __init__(self, values=None, counter=None): def __init__(self, values=None, counter=None):
# set values of signature jumps # builed counter based on values of signature jumps
if counter is None: if counter is None:
counter = collections.Counter() counter = collections.Counter()
if values is None: if values is None:
values = [] values = []
else:
msg = "Signature function is defined on the interval [0, 1)." msg = "Signature function is defined on the interval [0, 1)."
assert all(k < 1 for k, v in values), msg assert all(k < 1 for k, v in values), msg
counter2 = collections.Counter({ k : v for k, v in values})
for k, v in values: for k, v in values:
counter[k] += v counter[k] += v
assert counter2 == counter
self.cnt_signature_jumps = counter self.cnt_signature_jumps = counter
self.tikz_plot("bum.tex") # self.tikz_plot("bum.tex")
def is_zero_everywhere(self): def is_zero_everywhere(self):
@ -41,7 +40,6 @@ class SignatureFunction(object):
counter.update(collections.Counter({ k / 2 : v for k, v in items})) counter.update(collections.Counter({ k / 2 : v for k, v in items}))
new_data = [] new_data = []
for jump_arg, jump in self.cnt_signature_jumps.items(): for jump_arg, jump in self.cnt_signature_jumps.items():
if jump != 0:
new_data.append((jump_arg/2, jump)) new_data.append((jump_arg/2, jump))
new_data.append((1/2 + jump_arg/2, jump)) new_data.append((1/2 + jump_arg/2, jump))
assert SignatureFunction(values=new_data) == SignatureFunction(counter=counter) assert SignatureFunction(values=new_data) == SignatureFunction(counter=counter)
@ -60,7 +58,6 @@ class SignatureFunction(object):
counter[2 * jump_arg] = jump counter[2 * jump_arg] = jump
assert SignatureFunction(values=new_data) == SignatureFunction(counter=counter) assert SignatureFunction(values=new_data) == SignatureFunction(counter=counter)
return SignatureFunction(values=new_data) return SignatureFunction(values=new_data)
def minus_square_root(self): def minus_square_root(self):
@ -202,47 +199,100 @@ class SignatureFunction(object):
class TorusCable(object): class TorusCable(object):
def __init__(self, knot_formula, k_vector=None, q_vector=None): def __init__(self, knot_formula, k_vector=None, q_vector=None):
self._knot_formula = knot_formula
# q_i = 2 * k_i + 1 # q_i = 2 * k_i + 1
if k_vector is None: if k_vector is not None:
if q_vector is None:
# TBD docstring
print("Please give a list of k (k_vector) \
or q values (q_vector).")
msg = ""
raise ValueError(msg)
else:
k_vector = [(q - 1)/2 for q in q_vector]
elif q_vector is None:
q_vector = [2 * k + 1 for k in k_vector]
self.knot_formula = knot_formula
self.k_vector = k_vector self.k_vector = k_vector
elif q_vector is not None:
self.q_vector = q_vector self.q_vector = q_vector
k = k_vector else:
self.knot_sum = eval(knot_formula) msg = "Please give a list of k (k_vector) or q values (q_vector)."
self.knot_description = self.set_knot_descrption() raise ValueError(msg)
self.__sigma_function = None
# TBD property function # TBD property function
self.signature_as_function_of_theta = None self._sigma_function = None
self.signature_as_function_of_theta = self.get_signature_as_function_of_theta() self._signature_as_function_of_theta = None
# self.signature_as_function_of_theta = None
# SIGMA & SIGNATURE
@property
def sigma_function(self):
if self._sigma_function is None:
self._sigma_function = self.get_sigma_function()
return self._sigma_function
@property
def signature_as_function_of_theta(self):
if self._signature_as_function_of_theta is None:
self._signature_as_function_of_theta = \
self.get_signature_as_function_of_theta()
return self._signature_as_function_of_theta
@property
def knot_formula(self):
return self._knot_formula
@property
def knot_description(self):
return self._knot_description
@property
def knot_sum(self):
return self._knot_sum
@knot_sum.setter
def knot_sum(self, val):
self._knot_sum = val
self._knot_description = self.get_knot_descrption(val)
self._number_of_summands = len(val)
@property
def number_of_summands(self):
return self._number_of_summands
@property
def k_vector(self):
return self._k_vector
@k_vector.setter
def k_vector(self, k):
self._k_vector = k
self.knot_sum = eval(self.knot_formula)
self._q_vector = [2 * k_val + 1 for k_val in k]
@property
def q_vector(self):
return self._q_vector
@q_vector.setter
def q_vector(self, new_q_vector):
self.k_vector = [(q - 1)/2 for q in new_q_vector]
def update(self, other): def update(self, other):
# TBD knot_formula etc. # TBD knot_formula etc.
number_of_summands = len(self.knot_sum) print("*" * 100)
self.knot_description += " # " + other.knot_description print("BEFORE")
self.knot_formula = self.knot_formula[:-1] + ",\n" + \
other.knot_formula[1:]
print(self.knot_sum)
self.knot_sum += other.knot_sum
# self.signature_as_function_of_theta = \
# self.get_signature_as_function_of_theta() + \
# other.get_signature_as_function_of_theta()
print(self.knot_description) print(self.knot_description)
print(self.knot_formula) print(self.knot_formula)
print(self.knot_sum) print(self.knot_sum)
def __get_sigma_function(self): self._knot_formula = self.knot_formula[:-1] + ",\n" + \
other.knot_formula[1:]
self.knot_sum += other.knot_sum
# self.signature_as_function_of_theta = \
# self.get_signature_as_function_of_theta() + \
# other.get_signature_as_function_of_theta()
print("*" * 100)
print("AFTER")
print(self.knot_description)
print(self.knot_formula)
print(self.knot_sum)
def get_sigma_function(self):
k_1, k_2, k_3, k_4 = [abs(k) for k in self.k_vector] k_1, k_2, k_3, k_4 = [abs(k) for k in self.k_vector]
last_q = 2 * k_4 + 1 last_q = 2 * k_4 + 1
ksi = 1/last_q ksi = 1/last_q
@ -273,71 +323,6 @@ class TorusCable(object):
return sigma_v return sigma_v
return sigma_function return sigma_function
def __get_signature_as_function_of_theta(self, **key_args):
if 'verbose' in key_args:
verbose_default = key_args['verbose']
else:
verbose_default = False
def signature_as_function_of_theta(*thetas, **kwargs):
verbose = verbose_default
if 'verbose' in kwargs:
verbose = kwargs['verbose']
len_a = len(self.knot_sum)
len_t = len(thetas)
# call with no arguments
if len_t == 0:
return signature_as_function_of_theta(*(len_a * [0]))
if len_t != len_a:
if isinstance(thetas, Iterable) and len(thetas[0]) == len_a:
thetas = thetas[0]
else:
msg = "This function takes exactly " + str(len_a) + \
" arguments or no argument at all (" + str(len_t) + \
" given)."
raise TypeError(msg)
sf = SignatureFunction()
untwisted_part = SignatureFunction()
# for each cable knot in cable sum apply theta
for i, knot in enumerate(self.knot_sum):
try:
ssf = self.get_summand_signature_as_theta_function(*knot)
plus, _, up = ssf(thetas[i])
# sf += ssf(thetas[i])
sf += plus
untwisted_part += up
# in case wrong theata value was given
except ValueError as e:
print("ValueError: " + str(e.args[0]) +\
" Please change " + str(i + 1) + ". parameter.")
return None
a = thetas[0]
if all(i == a or i == self.q_vector[-1] - a for i in thetas):
print()
print("\n" + "*" * 100)
print(self.knot_description)
print("one vector " + str(thetas))
print("max sf " + str(sf.is_big()))
print()
# assert untwisted_part.is_zero_everywhere()
if verbose:
print()
print(str(thetas))
print(sf)
msg = "tota signature jump = " + str(sf.total_sign_jump())
msg += "\nfunction\n" + str(sf)
assert sf.total_sign_jump() == 0, msg
return sf
signature_as_function_of_theta.__doc__ =\
signature_as_function_of_theta_docstring
return signature_as_function_of_theta
@staticmethod @staticmethod
def get_blanchfield_for_pattern(k_n, theta): def get_blanchfield_for_pattern(k_n, theta):
if theta == 0: if theta == 0:
@ -395,7 +380,6 @@ class TorusCable(object):
return SignatureFunction(values=results) return SignatureFunction(values=results)
@staticmethod @staticmethod
def get_untwisted_signature_function(j): def get_untwisted_signature_function(j):
# return the signature function of the T_{2,2k+1} torus knot # return the signature function of the T_{2,2k+1} torus knot
@ -406,10 +390,10 @@ class TorusCable(object):
for a in range(k + 1, 2 * k + 1)]) for a in range(k + 1, 2 * k + 1)])
return SignatureFunction(values=w) return SignatureFunction(values=w)
@staticmethod
def set_knot_descrption(self): def get_knot_descrption(knot_sum):
description = "" description = ""
for knot in self.knot_sum: for knot in knot_sum:
if knot[0] < 0: if knot[0] < 0:
description += "-" description += "-"
description += "T(" description += "T("
@ -418,11 +402,69 @@ class TorusCable(object):
description = description[:-2] + ") # " description = description[:-2] + ") # "
return description[:-3] return description[:-3]
def get_signature_as_function_of_theta(self, verbose=False):
if self.signature_as_function_of_theta is None: def get_signature_as_function_of_theta(self, **key_args):
self.signature_as_function_of_theta = \ if 'verbose' in key_args:
self.__get_signature_as_function_of_theta(verbose=verbose) verbose_default = key_args['verbose']
return self.signature_as_function_of_theta else:
verbose_default = False
def signature_as_function_of_theta(*thetas, **kwargs):
verbose = verbose_default
if 'verbose' in kwargs:
verbose = kwargs['verbose']
len_a = len(self.knot_sum)
len_t = len(thetas)
# call with no arguments
if len_t == 0:
return signature_as_function_of_theta(*(len_a * [0]))
if len_t != len_a:
if isinstance(thetas, Iterable) and len(thetas[0]) == len_a:
thetas = thetas[0]
else:
msg = "This function takes exactly " + str(len_a) + \
" arguments or no argument at all (" + str(len_t) + \
" given)."
raise TypeError(msg)
sf = SignatureFunction()
untwisted_part = SignatureFunction()
# for each cable knot in cable sum apply theta
for i, knot in enumerate(self.knot_sum):
try:
ssf = self.get_summand_signature_as_theta_function(*knot)
plus, _, up = ssf(thetas[i])
# sf += ssf(thetas[i])
sf += plus
untwisted_part += up
# in case wrong theata value was given
except ValueError as e:
print("ValueError: " + str(e.args[0]) +\
" Please change " + str(i + 1) + ". parameter.")
return None
a = thetas[0]
if all(i == a or i == self.q_vector[-1] - a for i in thetas):
print()
print("\n" + "*" * 100)
print(self.knot_description)
print("one vector " + str(thetas))
print("max sf " + str(sf.is_big()))
print()
# assert untwisted_part.is_zero_everywhere()
if verbose:
print()
print(str(thetas))
print(sf)
msg = "tota signature jump = " + str(sf.total_sign_jump())
msg += "\nfunction\n" + str(sf)
assert sf.total_sign_jump() == 0, msg
return sf
signature_as_function_of_theta.__doc__ =\
signature_as_function_of_theta_docstring
return signature_as_function_of_theta
def get_summand_signature_as_theta_function(self, *knot_as_k_values): def get_summand_signature_as_theta_function(self, *knot_as_k_values):
def get_summand_signture_function(theta): def get_summand_signture_function(theta):
@ -464,46 +506,28 @@ class TorusCable(object):
number_of_combinations *= (2 * abs(knot[-1]) + 1) number_of_combinations *= (2 * abs(knot[-1]) + 1)
return number_of_combinations return number_of_combinations
# to be removed
def check_combinations_in_range(self, range_product):
if self.__sigma_function is None:
self.__sigma_function = self.__get_sigma_function()
return self.__check_combinations_in_range(range_product, SIGMA)
# to be removed
def calculate_sigma(self, theta_vector):
if self.__sigma_function is None:
self.__sigma_function = self.__get_sigma_function()
return self.__sigma_function(theta_vector)
def is_sigma_for_vector_class_big(self, theta_vector):
if self.__sigma_function is None:
self.__sigma_function = self.__get_sigma_function()
return self.__is_value_for_vector_class_big(theta_vector, SIGMA)
# searching for signature == 0 # searching for signature == 0
def check_for_null_theta_combinations(self, verbose=False): def check_for_null_theta_combinations(self, verbose=False):
list_of_good_vectors= [] list_of_good_vectors= []
number_of_null_comb = 0 number_of_null_comb = 0
f = self.get_signature_as_function_of_theta(verbose=verbose) f = self.signature_as_function_of_theta
range_list = [range(abs(knot[-1]) + 1) for knot in self.knot_sum] range_list = [range(abs(knot[-1]) + 1) for knot in self.knot_sum]
for theta_vector in it.product(*range_list): for theta_vector in it.product(*range_list):
if f(*theta_vector, verbose=False).is_zero_everywhere(): if f(*theta_vector).is_zero_everywhere():
list_of_good_vectors.append(theta_vector) list_of_good_vectors.append(theta_vector)
m = len([theta for theta in theta_vector if theta != 0]) m = len([theta for theta in theta_vector if theta != 0])
number_of_null_comb += 2^m number_of_null_comb += 2^m
return number_of_null_comb, list_of_good_vectors return number_of_null_comb, list_of_good_vectors
# searching for sigma > 5 + #(v_i != 0) # searching for signature or sigma > 5 + #(v_i != 0)
def __check_all_combinations_in_ranges(self, list_of_ranges, def check_all_combinations_in_ranges(self, list_of_ranges,
sigma_or_sign, sigma_or_sign,
print_results=False): print_results=False):
all_combinations_pass = True all_combinations_pass = True
all_bad_vectors = [] all_bad_vectors = []
number_of_all_good_v = 0 number_of_all_good_v = 0
for i, range_product in enumerate(list_of_ranges): for i, range_product in enumerate(list_of_ranges):
good_v, bad_v = self.__check_combinations_in_range(range_product, good_v, bad_v = self.check_combinations_in_range(range_product,
sigma_or_sign) sigma_or_sign)
number_of_all_good_v += len(good_v) number_of_all_good_v += len(good_v)
all_bad_vectors = list(it.chain(all_bad_vectors, bad_v)) all_bad_vectors = list(it.chain(all_bad_vectors, bad_v))
@ -523,7 +547,7 @@ class TorusCable(object):
return all_combinations_pass return all_combinations_pass
# searching for signature or sigma > 5 + #(v_i != 0) # searching for signature or sigma > 5 + #(v_i != 0)
def __check_combinations_in_range(self, range_product, sigma_or_sign): def check_combinations_in_range(self, range_product, sigma_or_sign):
bad_vectors = [] bad_vectors = []
good_vectors = [] good_vectors = []
last_q = self.q_vector[-1] last_q = self.q_vector[-1]
@ -536,7 +560,7 @@ class TorusCable(object):
# pass # pass
# else: # else:
# continue # continue
if self.__is_value_for_vector_class_big(vector, sigma_or_sign): if self.is_value_for_vector_class_big(vector, sigma_or_sign):
good_vectors.append(vector) good_vectors.append(vector)
else: else:
# print(vector) # print(vector)
@ -565,7 +589,7 @@ class TorusCable(object):
# check sigma or signature function value # check sigma or signature function value
# for all v = s * [a_1, a_2, a_3, a_4] for s in [1, last_q - 1] # for all v = s * [a_1, a_2, a_3, a_4] for s in [1, last_q - 1]
def __is_value_for_vector_class_big(self, theta_vector, sigma_or_sign): def is_value_for_vector_class_big(self, theta_vector, sigma_or_sign):
[a_1, a_2, a_3, a_4] = theta_vector [a_1, a_2, a_3, a_4] = theta_vector
q_4 = self.q_vector[-1] q_4 = self.q_vector[-1]
k_4 = self.k_vector[-1] k_4 = self.k_vector[-1]
@ -575,7 +599,7 @@ class TorusCable(object):
if sigma_or_sign == SIGNATURE: if sigma_or_sign == SIGNATURE:
f = self.signature_as_function_of_theta f = self.signature_as_function_of_theta
else: else:
f = self.__sigma_function f = self.sigma_function
# print(theta_vector, end="\t") # print(theta_vector, end="\t")
for shift in range(1, k_4 + 1): for shift in range(1, k_4 + 1):
@ -583,13 +607,13 @@ class TorusCable(object):
[a_1, a_2, a_3, a_4]] [a_1, a_2, a_3, a_4]]
if sigma_or_sign == SIGNATURE: if sigma_or_sign == SIGNATURE:
sf = f(shifted_theta) sf = f(shifted_theta)
sigma_v = sf.is_big() sig_v = sf.is_big()
else: else:
sigma_v = f(shifted_theta) sig_v = f(shifted_theta)
print(sigma_v, end=" ") print(sig_v, end=" ")
if abs(sigma_v) > abs(max_sigma): if abs(sig_v) > abs(max_sigma):
max_sigma = sigma_v max_sig = sig_v
if abs(sigma_v) > 5 + np.count_nonzero(shifted_theta): if abs(sig_v) > 5 + np.count_nonzero(shifted_theta):
# print("\tok " + str(sigma_v)) # print("\tok " + str(sigma_v))
return True return True
# print("\tbad class " + str(max_sigma)) # print("\tbad class " + str(max_sigma))
@ -602,15 +626,7 @@ class TorusCable(object):
verbose=False): verbose=False):
if print_results: if print_results:
print(self.knot_description) # , end="\t\t\t") print(self.knot_description) # , end="\t\t\t")
if sigma_or_sign == SIGMA: if self.check_all_combinations_in_ranges(list_of_ranges,
if self.__sigma_function is None:
self.__sigma_function = self.__get_sigma_function()
else:
if self.signature_as_function_of_theta is None:
self.signature_as_function_of_theta= \
self.__get_signature_as_function_of_theta()
if self.__check_all_combinations_in_ranges(list_of_ranges,
sigma_or_sign, sigma_or_sign,
print_results=print_results): print_results=print_results):
return True return True
@ -781,12 +797,12 @@ TorusCable.get_number_of_combinations_of_theta.__doc__ = \
and q_j is the last q parameter for the component (a single cable) and q_j is the last q parameter for the component (a single cable)
""" """
TorusCable.set_knot_descrption.__doc__ = \ TorusCable.get_knot_descrption.__doc__ = \
""" """
Arguments: Arguments:
arbitrary number of lists of numbers, each list encodes a single cable. arbitrary number of lists of numbers, each list encodes a single cable.
Examples: Examples:
sage: set_knot_descrption([1, 3], [2], [-1, -2], [-3]) 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)' 'T(2, 3; 2, 7) # T(2, 5) # -T(2, 3; 2, 5) # -T(2, 7)'
""" """