functions searching for large signature values
This commit is contained in:
parent
2477c79297
commit
90322e0d19
@ -1,37 +1,6 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
# TBD: read about Factory Method, variable in docstring, sage documentation
|
# TBD: read about Factory Method, variable in docstring, sage documentation
|
||||||
def calculate_form(x, y, q4):
|
|
||||||
x1, x2, x3, x4 = x
|
|
||||||
y1, y2, y3, y4 = y
|
|
||||||
form = (x1 * y1 - x2 * y2 + x3 * y3 - x4 * y4) % q_4
|
|
||||||
# TBD change for ring modulo q_4
|
|
||||||
return form
|
|
||||||
|
|
||||||
def check_condition(v, q4):
|
|
||||||
if calculate_form(v, v, q4):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def find_v(q4):
|
|
||||||
results = []
|
|
||||||
for i in range(q4):
|
|
||||||
for j in range(q4):
|
|
||||||
for k in range(q4):
|
|
||||||
for m in range(q4):
|
|
||||||
if check_condition([i, j, k, m], q_4):
|
|
||||||
results.add(v)
|
|
||||||
return results
|
|
||||||
|
|
||||||
def check_inequality(q, v):
|
|
||||||
a1, a2, a3, a4 = v
|
|
||||||
q1, q2, q3, q4 = q
|
|
||||||
pattern = [q1, q2, q4],[-q2, -q4],[q3, q4],[-q1, -q3, -q4]
|
|
||||||
signature_function_generator = get_function_of_theta_for_sum(pattern)
|
|
||||||
signature_function_for_sum = signature_function_generator(a1, a2, a3, a4)
|
|
||||||
|
|
||||||
# sigma_v = sigma(q4, a1) - s(a2) + s(a3) - s(a4)
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
This script calculates signature functions for knots (cable sums).
|
This script calculates signature functions for knots (cable sums).
|
||||||
@ -45,9 +14,9 @@ corresponds to a cable knot, e.g. a list
|
|||||||
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).
|
||||||
|
|
||||||
To calculate the number of characters for which signature function vanish use
|
To calculate the number of characters for which signature function vanish use
|
||||||
the function eval_cable_for_thetas as shown below.
|
the function eval_cable_for_null_signature as shown below.
|
||||||
|
|
||||||
sage: eval_cable_for_thetas([[1, 3], [2], [-1, -2], [-3]])
|
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)
|
T(2, 3; 2, 7) # T(2, 5) # -T(2, 3; 2, 5) # -T(2, 7)
|
||||||
Zero cases: 1
|
Zero cases: 1
|
||||||
@ -57,12 +26,24 @@ Zero theta combinations:
|
|||||||
|
|
||||||
sage:
|
sage:
|
||||||
|
|
||||||
|
The numbers given to the function eval_cable_for_null_signature are k-values for each
|
||||||
The numbers given to the function eval_cable_for_thetas are k-values for each
|
|
||||||
component/cable in a direct sum.
|
component/cable in a direct sum.
|
||||||
|
|
||||||
To calculate signature function for a knot and a theta value, use function
|
To calculate signature function for a knot and a theta value, use function
|
||||||
get_function_of_theta_for_sum (see help/docstring for details).
|
get_function_of_theta_for_sum (see help/docstring for details).
|
||||||
|
|
||||||
|
About notation:
|
||||||
|
Cables that we work with follow a schema:
|
||||||
|
T(2, q_0; 2, q_1; 2, q_3) # -T(2, q_1; 2, q_3) #
|
||||||
|
# T(2, q_2; 2, q_3) # -T(2, q_0; 2, q_2; 2, q_3)
|
||||||
|
In knot_formula each k[i] is related with some q_i value, where
|
||||||
|
q_i = 2*k[i] + 1.
|
||||||
|
So we can work in the following steps:
|
||||||
|
1) choose a schema/formula by changing the value of knot_formula
|
||||||
|
2) set each q_i all or choose range in which q_i should varry
|
||||||
|
3) choose vector v / theata vector.
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@ -72,6 +53,7 @@ import collections
|
|||||||
import inspect
|
import inspect
|
||||||
import itertools as it
|
import itertools as it
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
@ -81,30 +63,23 @@ class MySettings(object):
|
|||||||
|
|
||||||
# is the ratio restriction for values in k_vector taken into account
|
# is the ratio restriction for values in k_vector taken into account
|
||||||
# False flag is usefull to make quick script tests
|
# False flag is usefull to make quick script tests
|
||||||
self.only_slice_candidates = True
|
# self.only_slice_candidates = True
|
||||||
# self.only_slice_candidates = False
|
self.only_slice_candidates = False
|
||||||
|
|
||||||
# knot_sum_formula is a schema for knots which signature function
|
# knot_formula is a schema for knots which signature function
|
||||||
# will be calculated
|
# will be calculated
|
||||||
self.knot_sum_formula = "[[k[0], k[1], k[2]], [k[3], k[4]], \
|
self.knot_formula = "[[k[0], k[1], k[3]], [-k[1], -k[3]], \
|
||||||
[-k[0], -k[3], -k[4]], [-k[1], -k[2]]]"
|
[k[2], k[3]], [-k[0], -k[2], -k[3]]]"
|
||||||
"""
|
|
||||||
About notation:
|
|
||||||
Cables that we work with follow a schema:
|
|
||||||
T(2, q_0; 2, q_1; 2, q_2) # T(2, q_1; 2, q_2) #
|
|
||||||
# -T(2, q_3; 2, q_2) # -T(2, q_0; 2, q_3; 2, q_2)
|
|
||||||
In knot_sum_formula each k[i] is related with some q_i value, where
|
|
||||||
q_i = 2*k[i] + 1.
|
|
||||||
So we can work in the following steps:
|
|
||||||
1) choose a schema/formula by changing the value of knot_sum_formula
|
|
||||||
2) set each q_i all or choose range in which q_i should varry
|
|
||||||
3) choose vector v / theata vector.
|
|
||||||
|
|
||||||
"""
|
|
||||||
# self.knot_sum_formula = "[[k[0], k[1], k[2]], [k[3]],\
|
# self.knot_formula = "[[k[0], k[1], k[2]], [k[3], k[4]], \
|
||||||
|
# [-k[0], -k[3], -k[4]], [-k[1], -k[2]]]"
|
||||||
|
# self.knot_formula = "[[k[0], k[1], k[2]], [k[3]],\
|
||||||
# [-k[0], -k[1], -k[3]], [-k[2]]]"
|
# [-k[0], -k[1], -k[3]], [-k[2]]]"
|
||||||
self.default_limit = 3
|
self.default_limit = 3
|
||||||
|
|
||||||
|
self.verbose = True
|
||||||
|
|
||||||
|
|
||||||
class SignatureFunction(object):
|
class SignatureFunction(object):
|
||||||
"""
|
"""
|
||||||
@ -190,72 +165,200 @@ class SignatureFunction(object):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return ''.join([str(jump_arg) + ": " + str(jump) + "\n"
|
return ''.join([str(jump_arg) + ": " + str(jump) + "\n"
|
||||||
for jump_arg, jump in sorted(self.data.items())])
|
for jump_arg, jump in sorted(self.data.items())])
|
||||||
|
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 main(arg):
|
def main(arg):
|
||||||
"""
|
|
||||||
This function is run if the script was called from the terminal.
|
|
||||||
It calls another function, perform_calculations,
|
|
||||||
to calculate signature functions for a schema
|
|
||||||
of a cable sum defined in the class MySettings.
|
|
||||||
Optionaly a parameter (a limit for k_0 value) can be given.
|
|
||||||
Thought to be run for time consuming calculations.
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
new_limit = int(arg[1])
|
new_limit = int(arg[1])
|
||||||
except:
|
except:
|
||||||
new_limit = None
|
new_limit = None
|
||||||
perform_calculations(limit=new_limit)
|
search_for_large_signature_value(limit=new_limit)
|
||||||
|
# search_for_null_signature_value(limit=new_limit)
|
||||||
|
|
||||||
|
|
||||||
def perform_calculations(knot_sum_formula=None, limit=None):
|
def search_for_large_signature_value(knot_formula=None,
|
||||||
"""
|
limit=None, verbose=None):
|
||||||
This function calculates signature functions for knots constracted
|
|
||||||
accordinga a schema for a cable sum. The schema is given as an argument
|
|
||||||
or defined in the class MySettings.
|
|
||||||
Results of calculations will be writen to a file and the stdout.
|
|
||||||
limit is the upper bound for the first value in k_vector,
|
|
||||||
i.e k[0] value in a cable sum, where q_0 = 2 * k[0] + 1.
|
|
||||||
|
|
||||||
(the number of knots that will be constracted depends on limit value).
|
|
||||||
For each knot/cable sum the function eval_cable_for_thetas is called.
|
|
||||||
eval_cable_for_thetas calculetes the number of all possible thetas
|
|
||||||
(characters) and the number of combinations for which signature function
|
|
||||||
equeles zero. In case the first number is larger than squere of the second,
|
|
||||||
eval_cable_for_thetas returns None (i.e. the knot can not be slice).
|
|
||||||
Data for knots that are candidates for slice knots are saved to a file.
|
|
||||||
"""
|
|
||||||
|
|
||||||
settings = MySettings()
|
|
||||||
if limit is None:
|
if limit is None:
|
||||||
limit = settings.default_limit
|
limit = config.default_limit
|
||||||
if knot_sum_formula is None:
|
if knot_formula is None:
|
||||||
knot_sum_formula = settings.knot_sum_formula
|
knot_formula = config.knot_formula
|
||||||
|
if verbose is None:
|
||||||
|
vebose = config.verbose
|
||||||
|
|
||||||
k_vector_size = extract_max(knot_sum_formula) + 1
|
k_vector_size = extract_max(knot_formula) + 1
|
||||||
combinations = it.combinations_with_replacement(range(1, limit + 1),
|
limit = max(limit, k_vector_size)
|
||||||
k_vector_size)
|
print limit
|
||||||
|
combinations = it.combinations(range(1, limit + 1), k_vector_size)
|
||||||
with open(settings.f_results, 'w') as f_results:
|
|
||||||
for k in combinations:
|
for k in combinations:
|
||||||
# print
|
print
|
||||||
# print k
|
print k
|
||||||
|
# P = Primes()
|
||||||
|
# sage: P.unrank(0)
|
||||||
|
# 2
|
||||||
|
# sage: P.unrank(5)
|
||||||
|
# 13
|
||||||
|
# sage: P.unrank(42)
|
||||||
|
return None
|
||||||
|
with open(config.f_results, 'w') as f_results:
|
||||||
|
for k in combinations:
|
||||||
|
if verbose:
|
||||||
|
print
|
||||||
|
print k
|
||||||
# TBD: maybe the following condition or the function
|
# TBD: maybe the following condition or the function
|
||||||
# get_shifted_combination should be redefined to a dynamic version
|
# get_shifted_combination should be redefined to a dynamic version
|
||||||
if settings.only_slice_candidates and k_vector_size == 5:
|
if config.only_slice_candidates and k_vector_size == 5:
|
||||||
k = get_shifted_combination(k)
|
k = get_shifted_combination(k)
|
||||||
# print k
|
# print k
|
||||||
knot_sum = eval(knot_sum_formula)
|
knot_sum = eval(knot_formula)
|
||||||
|
print "knot_sum"
|
||||||
|
print knot_sum
|
||||||
|
|
||||||
if is_trivial_combination(knot_sum):
|
if is_trivial_combination(knot_sum):
|
||||||
|
if verbose:
|
||||||
|
print "\nTrivial combination" + str(knot_sum)
|
||||||
continue
|
continue
|
||||||
result = eval_cable_for_thetas(knot_sum, print_results=False)
|
result = eval_cable_for_large_signature(knot_sum,
|
||||||
|
print_results=False)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
knot_description, null_comb, all_comb = result
|
knot_description, null_comb, all_comb = result
|
||||||
line = (str(k) + ", " + str(null_comb) + ", " +
|
line = (str(k) + ", " + str(null_comb) + ", " +
|
||||||
str(all_comb) + "\n")
|
str(all_comb) + "\n")
|
||||||
f_results.write(line)
|
f_results.write(line)
|
||||||
|
|
||||||
|
def eval_cable_for_large_signature(knot_sum, print_results=True, verbose=None):
|
||||||
|
if verbose is None:
|
||||||
|
verbose = config.verbose
|
||||||
|
if verbose:
|
||||||
|
print "\neval_cable_for_large_signature"
|
||||||
|
if len(knot_sum) != 4:
|
||||||
|
print "Wrong number of cable direct summands!"
|
||||||
|
return None
|
||||||
|
q = 2 * abs(knot_sum[-1][-1]) + 1
|
||||||
|
print "q is " + str(q)
|
||||||
|
|
||||||
|
f = get_function_of_theta_for_sum(*knot_sum, verbose=False)
|
||||||
|
knot_description = get_knot_descrption(*knot_sum)
|
||||||
|
all_combinations = get_number_of_combinations(*knot_sum)
|
||||||
|
|
||||||
|
null_combinations = 0
|
||||||
|
zero_theta_combinations = []
|
||||||
|
|
||||||
|
ranges_list = [range(abs(knot[-1]) + 1) for knot in knot_sum]
|
||||||
|
if verbose:
|
||||||
|
print "eval_cable_for_large_signature - knot_description: "
|
||||||
|
print knot_description
|
||||||
|
for v_theta in it.product(*ranges_list):
|
||||||
|
y = f(*v_theta).value(1/2)
|
||||||
|
print y
|
||||||
|
if abs(y) > 5 + np.count_nonzero(v_theta):
|
||||||
|
print "hura hura"
|
||||||
|
# == 0:
|
||||||
|
# zero_theta_combinations.append(v_theta)
|
||||||
|
# m = len([theta for theta in v_theta if theta != 0])
|
||||||
|
# null_combinations += 2^m
|
||||||
|
# else:
|
||||||
|
# assert sum(v_theta) != 0
|
||||||
|
|
||||||
|
if print_results:
|
||||||
|
print
|
||||||
|
print knot_description
|
||||||
|
print "Zero cases: " + str(null_combinations)
|
||||||
|
print "All cases: " + str(all_combinations)
|
||||||
|
if zero_theta_combinations:
|
||||||
|
print "Zero theta combinations: "
|
||||||
|
for el in zero_theta_combinations:
|
||||||
|
print el
|
||||||
|
if null_combinations^2 >= all_combinations:
|
||||||
|
return knot_description, null_combinations, all_combinations
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def search_for_null_signature_value(knot_formula=None, limit=None):
|
||||||
|
if limit is None:
|
||||||
|
limit = config.default_limit
|
||||||
|
if knot_formula is None:
|
||||||
|
knot_formula = config.knot_formula
|
||||||
|
|
||||||
|
k_vector_size = extract_max(knot_formula) + 1
|
||||||
|
combinations = it.combinations_with_replacement(range(1, limit + 1),
|
||||||
|
k_vector_size)
|
||||||
|
|
||||||
|
with open(config.f_results, 'w') as f_results:
|
||||||
|
for k in combinations:
|
||||||
|
# print
|
||||||
|
# print k
|
||||||
|
# TBD: maybe the following condition or the function
|
||||||
|
# get_shifted_combination should be redefined to a dynamic version
|
||||||
|
if confi.only_slice_candidates and k_vector_size == 5:
|
||||||
|
k = get_shifted_combination(k)
|
||||||
|
# print k
|
||||||
|
knot_sum = eval(knot_formula)
|
||||||
|
|
||||||
|
if is_trivial_combination(knot_sum):
|
||||||
|
continue
|
||||||
|
result = search_for_thetas(knot_sum, print_results=False)
|
||||||
|
if result is not None:
|
||||||
|
knot_description, null_comb, all_comb = result
|
||||||
|
line = (str(k) + ", " + str(null_comb) + ", " +
|
||||||
|
str(all_comb) + "\n")
|
||||||
|
f_results.write(line)
|
||||||
|
|
||||||
|
def search_for_thetas(knot_sum, print_results=False, verbose=None):
|
||||||
|
if verbose is None:
|
||||||
|
vebose = confi.verbose
|
||||||
|
if verbose:
|
||||||
|
print "search_for_thetas"
|
||||||
|
f = get_function_of_theta_for_sum(*knot_sum)
|
||||||
|
knot_description = get_knot_descrption(*knot_sum)
|
||||||
|
all_combinations = get_number_of_combinations(*knot_sum)
|
||||||
|
|
||||||
|
large_value_combinations = 0
|
||||||
|
good_theta_list = []
|
||||||
|
|
||||||
|
ranges_list = [range(abs(knot[-1]) + 1) for knot in knot_sum]
|
||||||
|
if verbose:
|
||||||
|
print "knot_description:"
|
||||||
|
print knot_description
|
||||||
|
for v_theta in it.product(*ranges_list):
|
||||||
|
if (v_theta[0]^2 - v_theta[1]^2 + v_theta[2]^2 - v_theta[3]^2) % q:
|
||||||
|
print "ojojoj"
|
||||||
|
print (v_theta[0]^2 - v_theta[1]^2 + v_theta[2]^2 - v_theta[3]^2) % q
|
||||||
|
continue
|
||||||
|
print f(*v_theta).value(-1)
|
||||||
|
if f(*v_theta).value(-1):
|
||||||
|
print "Hip hip hura"
|
||||||
|
good_theta_list.append(v_theta)
|
||||||
|
m = len([theta for theta in v_theta if theta != 0])
|
||||||
|
large_value_combinations += 2^m
|
||||||
|
else:
|
||||||
|
print "smuteczek"
|
||||||
|
# else:
|
||||||
|
# assert sum(v_theta) != 0
|
||||||
|
|
||||||
|
if print_results:
|
||||||
|
print
|
||||||
|
print knot_description
|
||||||
|
print "Zero cases: " + str(null_combinations)
|
||||||
|
print "All cases: " + str(all_combinations)
|
||||||
|
if zero_theta_combinations:
|
||||||
|
print "Zero theta combinations: "
|
||||||
|
for el in zero_theta_combinations:
|
||||||
|
print el
|
||||||
|
if null_combinations^2 >= all_combinations:
|
||||||
|
return knot_description, null_combinations, all_combinations
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def is_trivial_combination(knot_sum):
|
def is_trivial_combination(knot_sum):
|
||||||
# for now is applicable only for schema that are sums of 4 cables
|
# for now is applicable only for schema that are sums of 4 cables
|
||||||
@ -279,19 +382,6 @@ def get_shifted_combination(combination):
|
|||||||
|
|
||||||
|
|
||||||
def get_blanchfield_for_pattern(k_n, theta):
|
def get_blanchfield_for_pattern(k_n, theta):
|
||||||
"""
|
|
||||||
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)
|
|
||||||
"""
|
|
||||||
|
|
||||||
if theta == 0:
|
if theta == 0:
|
||||||
a = get_untwisted_signature_function(k_n)
|
a = get_untwisted_signature_function(k_n)
|
||||||
return a.square_root() + a.minus_square_root()
|
return a.square_root() + a.minus_square_root()
|
||||||
@ -322,28 +412,7 @@ def get_blanchfield_for_pattern(k_n, theta):
|
|||||||
|
|
||||||
|
|
||||||
def get_cable_signature_as_theta_function(*arg):
|
def get_cable_signature_as_theta_function(*arg):
|
||||||
"""
|
|
||||||
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
|
|
||||||
"""
|
|
||||||
|
|
||||||
def get_signture_function(theta):
|
def get_signture_function(theta):
|
||||||
"""
|
|
||||||
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_cable_signature_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)
|
|
||||||
"""
|
|
||||||
|
|
||||||
# TBD: another formula (for t^2) description
|
# TBD: another formula (for t^2) description
|
||||||
|
|
||||||
k_n = abs(arg[-1])
|
k_n = abs(arg[-1])
|
||||||
@ -368,6 +437,7 @@ def get_cable_signature_as_theta_function(*arg):
|
|||||||
c = c.double_cover()
|
c = c.double_cover()
|
||||||
cable_signature += b + c
|
cable_signature += b + c
|
||||||
return cable_signature
|
return cable_signature
|
||||||
|
get_signture_function.__doc__ = get_signture_function_docsting
|
||||||
return get_signture_function
|
return get_signture_function
|
||||||
|
|
||||||
|
|
||||||
@ -381,7 +451,232 @@ def get_untwisted_signature_function(j):
|
|||||||
return SignatureFunction(w)
|
return SignatureFunction(w)
|
||||||
|
|
||||||
|
|
||||||
def get_function_of_theta_for_sum(*arg):
|
def get_function_of_theta_for_sum(*arg, **key_args):
|
||||||
|
if 'verbose' in key_args:
|
||||||
|
verbose_default = key_args['verbose']
|
||||||
|
else:
|
||||||
|
verbose_default = confi.verbose
|
||||||
|
def signature_function_for_sum(*thetas, **kwargs):
|
||||||
|
verbose = verbose_default
|
||||||
|
if 'verbose' in kwargs:
|
||||||
|
verbose = kwargs['verbose']
|
||||||
|
la = len(arg)
|
||||||
|
lt = len(thetas)
|
||||||
|
|
||||||
|
# call with no arguments
|
||||||
|
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 each cable in cable sum apply theta
|
||||||
|
for i, knot in enumerate(arg):
|
||||||
|
try:
|
||||||
|
sf += (get_cable_signature_as_theta_function(*knot))(thetas[i])
|
||||||
|
# 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
|
||||||
|
if verbose:
|
||||||
|
print
|
||||||
|
print str(thetas)
|
||||||
|
print sf
|
||||||
|
return sf
|
||||||
|
signature_function_for_sum.__doc__ = signature_function_for_sum_docstring
|
||||||
|
return signature_function_for_sum
|
||||||
|
|
||||||
|
|
||||||
|
def eval_cable_for_null_signature(knot_sum, print_results=True, verbose=None):
|
||||||
|
# search for zero combinations
|
||||||
|
if verbose is None:
|
||||||
|
vebose = confi.verbose
|
||||||
|
f = get_function_of_theta_for_sum(*knot_sum, verbose=False)
|
||||||
|
knot_description = get_knot_descrption(*knot_sum)
|
||||||
|
all_combinations = get_number_of_combinations(*knot_sum)
|
||||||
|
|
||||||
|
null_combinations = 0
|
||||||
|
zero_theta_combinations = []
|
||||||
|
|
||||||
|
ranges_list = [range(abs(knot[-1]) + 1) for knot in knot_sum]
|
||||||
|
if verbose:
|
||||||
|
print
|
||||||
|
print knot_description
|
||||||
|
for v_theta in it.product(*ranges_list):
|
||||||
|
if f(*v_theta, verbose=False).sum_of_absolute_values() == 0:
|
||||||
|
zero_theta_combinations.append(v_theta)
|
||||||
|
m = len([theta for theta in v_theta if theta != 0])
|
||||||
|
null_combinations += 2^m
|
||||||
|
# else:
|
||||||
|
# assert sum(v_theta) != 0
|
||||||
|
|
||||||
|
if print_results:
|
||||||
|
print
|
||||||
|
print knot_description
|
||||||
|
print "Zero cases: " + str(null_combinations)
|
||||||
|
print "All cases: " + str(all_combinations)
|
||||||
|
if zero_theta_combinations:
|
||||||
|
print "Zero theta combinations: "
|
||||||
|
for el in zero_theta_combinations:
|
||||||
|
print el
|
||||||
|
if null_combinations^2 >= all_combinations:
|
||||||
|
return knot_description, null_combinations, all_combinations
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def check_squares(a, k):
|
||||||
|
print
|
||||||
|
p = 2 * k + 1
|
||||||
|
k_0 = (p^2 - 1)/2
|
||||||
|
knot_sum = [[a, k], [k_0], [-a, -k_0], [-k]]
|
||||||
|
print get_knot_descrption(*knot_sum)
|
||||||
|
if a * 4 >= p or is_trivial_combination(knot_sum):
|
||||||
|
if a * 4 >= p:
|
||||||
|
print str(knot_sum)
|
||||||
|
print "a * 4 >= p"
|
||||||
|
else:
|
||||||
|
print "Trivial " + str(knot_sum)
|
||||||
|
return None
|
||||||
|
eval_cable_for_null_signature(knot_sum)
|
||||||
|
|
||||||
|
|
||||||
|
def get_number_of_combinations(*arg):
|
||||||
|
number_of_combinations = 1
|
||||||
|
for knot in arg:
|
||||||
|
number_of_combinations *= (2 * abs(knot[-1]) + 1)
|
||||||
|
return number_of_combinations
|
||||||
|
|
||||||
|
|
||||||
|
def extract_max(string):
|
||||||
|
numbers = re.findall('\d+', string)
|
||||||
|
numbers = map(int, numbers)
|
||||||
|
return max(numbers)
|
||||||
|
|
||||||
|
|
||||||
|
def mod_one(n):
|
||||||
|
return n - floor(n)
|
||||||
|
|
||||||
|
|
||||||
|
def get_knot_descrption(*arg):
|
||||||
|
description = ""
|
||||||
|
for knot in arg:
|
||||||
|
if knot[0] < 0:
|
||||||
|
description += "-"
|
||||||
|
description += "T("
|
||||||
|
for k in knot:
|
||||||
|
description += "2, " + str(2 * abs(k) + 1) + "; "
|
||||||
|
description = description[:-2] + ") # "
|
||||||
|
return description[:-3]
|
||||||
|
|
||||||
|
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_number_of_combinations.__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)
|
||||||
|
"""
|
||||||
|
|
||||||
|
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__ = \
|
||||||
|
"""
|
||||||
|
This function calculates signature functions for knots constracted
|
||||||
|
accordinga a schema for a cable sum. The schema is given as an argument
|
||||||
|
or defined in the class MySettings.
|
||||||
|
Results of calculations will be writen to a file and the stdout.
|
||||||
|
limit is the upper bound for the first value in k_vector,
|
||||||
|
i.e k[0] value in a cable sum, where q_0 = 2 * k[0] + 1.
|
||||||
|
|
||||||
|
(the number of knots that will be constracted depends on limit value).
|
||||||
|
For each knot/cable sum the function eval_cable_for_null_signature is called.
|
||||||
|
eval_cable_for_null_signature calculetes the number of all possible thetas
|
||||||
|
(characters) and the number of combinations for which signature function
|
||||||
|
equeles zero. In case the first number is larger than squere of the second,
|
||||||
|
eval_cable_for_null_signature returns None (i.e. the knot can not be slice).
|
||||||
|
Data for knots that are candidates for slice knots are saved to a file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
extract_max.__doc__ = \
|
||||||
|
"""
|
||||||
|
Return:
|
||||||
|
maximum of absolute values of numbers from given string
|
||||||
|
Examples:
|
||||||
|
sage: extract_max("([1, 3], [2], [-1, -2], [-10])")
|
||||||
|
10
|
||||||
|
sage: extract_max("3, 55, ewewe, -42, 3300, 50")
|
||||||
|
3300
|
||||||
|
"""
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
get_function_of_theta_for_sum.__doc__ = \
|
||||||
"""
|
"""
|
||||||
Function intended to construct signature function for a connected
|
Function intended to construct signature function for a connected
|
||||||
sum of multiple cables with varying theta parameter values.
|
sum of multiple cables with varying theta parameter values.
|
||||||
@ -435,7 +730,30 @@ def get_function_of_theta_for_sum(*arg):
|
|||||||
6/7: 0
|
6/7: 0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def signature_function_for_sum(*thetas, **kwargs):
|
get_cable_signature_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
|
||||||
|
"""
|
||||||
|
|
||||||
|
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_cable_signature_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_function_for_sum_docstring = \
|
||||||
"""
|
"""
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
@ -444,184 +762,52 @@ def get_function_of_theta_for_sum(*arg):
|
|||||||
Acept len(arg) arguments: for each cable one theta parameter.
|
Acept len(arg) arguments: for each cable one theta parameter.
|
||||||
If call with no arguments, all theta parameters are set to be 0.
|
If call with no arguments, all theta parameters are set to be 0.
|
||||||
"""
|
"""
|
||||||
if 'verbose' in kwargs:
|
|
||||||
verbose = kwargs['verbose']
|
|
||||||
else:
|
|
||||||
verbose = False
|
|
||||||
|
|
||||||
la = len(arg)
|
main.__doc__ = \
|
||||||
lt = len(thetas)
|
|
||||||
|
|
||||||
# call with no arguments
|
|
||||||
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 each cable in cable sum apply theta
|
|
||||||
for i, knot in enumerate(arg):
|
|
||||||
try:
|
|
||||||
sf += (get_cable_signature_as_theta_function(*knot))(thetas[i])
|
|
||||||
# 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
|
|
||||||
if verbose:
|
|
||||||
print
|
|
||||||
print str(*thetas)
|
|
||||||
print sf
|
|
||||||
return sf
|
|
||||||
return signature_function_for_sum
|
|
||||||
|
|
||||||
|
|
||||||
def eval_cable_for_thetas(knot_sum, print_results=True, verbose=False):
|
|
||||||
"""
|
"""
|
||||||
This function calculates all possible twisted signature functions for
|
This function is run if the script was called from the terminal.
|
||||||
a knot that is given as an argument. The knot should be encoded as a list
|
It calls another function, search_for_null_signature_value,
|
||||||
of its direct component. Each component schould be presented as a list
|
to calculate signature functions for a schema
|
||||||
of integers. This integers correspond to the k - values in each component/
|
of a cable sum defined in the class MySettings.
|
||||||
cable. If a component is a mirror image of a cable the minus sign should
|
Optionaly a parameter (a limit for k_0 value) can be given.
|
||||||
be written before each number for this component. For example:
|
Thought to be run for time consuming calculations.
|
||||||
eval_cable_for_thetas([[1, 8], [2], [-2, -8], [-2]])
|
|
||||||
eval_cable_for_thetas([[1, 2], [-1, -2]])
|
|
||||||
|
|
||||||
sage: eval_cable_for_thetas([[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_thetas are k-values for each
|
|
||||||
component/cable in a direct sum.
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
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 = 0
|
|
||||||
zero_theta_combinations = []
|
|
||||||
|
|
||||||
ranges_list = [range(abs(knot[-1]) + 1) for knot in knot_sum]
|
|
||||||
if verbose:
|
|
||||||
print
|
|
||||||
print knot_description
|
|
||||||
for v_theta in it.product(*ranges_list):
|
|
||||||
if f(*v_theta, verbose=verbose).sum_of_absolute_values() == 0:
|
|
||||||
zero_theta_combinations.append(v_theta)
|
|
||||||
m = len([theta for theta in v_theta if theta != 0])
|
|
||||||
null_combinations += 2^m
|
|
||||||
# else:
|
|
||||||
# assert sum(v_theta) != 0
|
|
||||||
|
|
||||||
if print_results:
|
|
||||||
print
|
|
||||||
print knot_description
|
|
||||||
print "Zero cases: " + str(null_combinations)
|
|
||||||
print "All cases: " + str(all_combinations)
|
|
||||||
if zero_theta_combinations:
|
|
||||||
print "Zero theta combinations: "
|
|
||||||
for el in zero_theta_combinations:
|
|
||||||
print el
|
|
||||||
if null_combinations^2 >= all_combinations:
|
|
||||||
return knot_description, null_combinations, all_combinations
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def check_squares(a, k):
|
|
||||||
print
|
|
||||||
p = 2 * k + 1
|
|
||||||
k_0 = (p^2 - 1)/2
|
|
||||||
knot_sum = [[a, k], [k_0], [-a, -k_0], [-k]]
|
|
||||||
print get_knot_descrption(*knot_sum)
|
|
||||||
if a * 4 >= p or is_trivial_combination(knot_sum):
|
|
||||||
if a * 4 >= p:
|
|
||||||
print str(knot_sum)
|
|
||||||
print "a * 4 >= p"
|
|
||||||
else:
|
|
||||||
print "Trivial " + str(knot_sum)
|
|
||||||
return None
|
|
||||||
eval_cable_for_thetas(knot_sum)
|
|
||||||
|
|
||||||
|
|
||||||
def get_number_of_combinations(*arg):
|
|
||||||
"""
|
|
||||||
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)
|
|
||||||
"""
|
|
||||||
number_of_combinations = 1
|
|
||||||
for knot in arg:
|
|
||||||
number_of_combinations *= (2 * abs(knot[-1]) + 1)
|
|
||||||
return number_of_combinations
|
|
||||||
|
|
||||||
|
|
||||||
def extract_max(string):
|
|
||||||
"""
|
|
||||||
Return:
|
|
||||||
maximum of absolute values of numbers from given string
|
|
||||||
Examples:
|
|
||||||
sage: extract_max("([1, 3], [2], [-1, -2], [-10])")
|
|
||||||
10
|
|
||||||
sage: extract_max("3, 55, ewewe, -42, 3300, 50")
|
|
||||||
3300
|
|
||||||
"""
|
|
||||||
numbers = re.findall('\d+', string)
|
|
||||||
numbers = map(int, numbers)
|
|
||||||
return max(numbers)
|
|
||||||
|
|
||||||
|
|
||||||
def mod_one(n):
|
|
||||||
"""
|
|
||||||
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
|
|
||||||
"""
|
|
||||||
return n - floor(n)
|
|
||||||
|
|
||||||
|
|
||||||
def get_knot_descrption(*arg):
|
|
||||||
"""
|
|
||||||
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)'
|
|
||||||
"""
|
|
||||||
description = ""
|
|
||||||
for knot in arg:
|
|
||||||
if knot[0] < 0:
|
|
||||||
description += "-"
|
|
||||||
description += "T("
|
|
||||||
for k in knot:
|
|
||||||
description += "2, " + str(2 * abs(k) + 1) + "; "
|
|
||||||
description = description[:-2] + ") # "
|
|
||||||
return description[:-3]
|
|
||||||
|
|
||||||
|
|
||||||
|
config = MySettings()
|
||||||
if __name__ == '__main__' and '__file__' in globals():
|
if __name__ == '__main__' and '__file__' in globals():
|
||||||
# not called in interactive mode as __file__ is not defined
|
# not called in interactive mode as __file__ is not defined
|
||||||
main(sys.argv)
|
main(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
# def calculate_form(x, y, q4):
|
||||||
|
# x1, x2, x3, x4 = x
|
||||||
|
# y1, y2, y3, y4 = y
|
||||||
|
# form = (x1 * y1 - x2 * y2 + x3 * y3 - x4 * y4) % q_4
|
||||||
|
# # TBD change for ring modulo q_4
|
||||||
|
# return form
|
||||||
|
#
|
||||||
|
# def check_condition(v, q4):
|
||||||
|
# if calculate_form(v, v, q4):
|
||||||
|
# return False
|
||||||
|
# return True
|
||||||
|
#
|
||||||
|
# def find_v(q4):
|
||||||
|
# results = []
|
||||||
|
# for i in range(q4):
|
||||||
|
# for j in range(q4):
|
||||||
|
# for k in range(q4):
|
||||||
|
# for m in range(q4):
|
||||||
|
# if check_condition([i, j, k, m], q_4):
|
||||||
|
# results.add(v)
|
||||||
|
# return results
|
||||||
|
#
|
||||||
|
# def check_inequality(q, v):
|
||||||
|
# a1, a2, a3, a4 = v
|
||||||
|
# q1, q2, q3, q4 = q
|
||||||
|
# pattern = [q1, q2, q4],[-q2, -q4],[q3, q4],[-q1, -q3, -q4]
|
||||||
|
# signature_function_generator = get_function_of_theta_for_sum(pattern)
|
||||||
|
# signature_function_for_sum = signature_function_generator(a1, a2, a3, a4)
|
||||||
|
#
|
||||||
|
# # sigma_v = sigma(q4, a1) - s(a2) + s(a3) - s(a4)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
Loading…
Reference in New Issue
Block a user