### ### LIBRARIES ### ###
import numpy as np
from cypari import pari
# import matplotlib.pyplot as plt
from typing import List, Callable, Tuple
from math import gcd
from functools import reduce
We can translate $Qfb \leftrightarrow sl(2) \leftarrow SL(2) \leftarrow RLw \leftrightarrow Ecf \leftarrow Qfb$.
We first translate $Qfb \leftrightarrow sl(2) \leftarrow SL(2)$.
def sl2_of_Qfb(Q):
l = pari.component(Q,1)
m = pari.component(Q,2)
r = pari.component(Q,3)
aa = pari.matrix(2,2,[-m,-2*r,2*l,m])
return aa/pari('2')
def Qfb_of_sl2(a):
l = a[1,0]
m = (a[1,1]-a[0,0])
r = -a[0,1]
# u = pari.gcd([l,m,r])
return pari.Qfb(l,m,r)
def sl2_of_SL2(A):
t = pari.trace(A)
a = 2*A-t
u = pari.gcd([a[0,0], a[0,1], a[1,0]])
if t!=0:
u *= pari.sign(t)
return(a/u)
'''Some tests'''
Q1 = pari.Qfb(11, 72, -66)
q1 = sl2_of_Qfb(Q1)
print(Q1, '\t', q1, '\t', Q1 == Qfb_of_sl2(q1))
Q2 = pari.Qfb(12, 72, -66)
q2 = sl2_of_Qfb(Q2)
print(q2, Q2, Q2 == Qfb_of_sl2(q2), '\n')
print(sl2_of_SL2(pari.matrix(2,2,[8,9,7,8])))
print(Qfb_of_sl2(sl2_of_SL2(pari.matrix(2,2,[8,9,7,8]))))
print(sl2_of_Qfb(Qfb_of_sl2(sl2_of_SL2(pari.matrix(2,2,[8,9,7,8])))), '\n')
M = pari("(1/d)*[-k, 0, 0, d^2-k^2 ; 0, 0, d, 0 ; 0, d, 0, 0 ; 1, 0, 0, k]")
Id4 = pari.matid(4)
PMX = pari.matdet(M-'X'*Id4)
print(pari.matdet(M), '\t', pari.trace(M))
print(PMX)
print(pari.factor(PMX))
print(pari.sign(1)==1, pari.gcd([1/2,2]))
Qfb(11, 72, -66) [-36, 66; 11, 36] True [-36, 66; 12, 36] Qfb(12, 72, -66) True [0, 9; 7, 0] Qfb(7, 0, -9) [0, 9; 7, 0] 1 0 (X^4 - 2*X^2 + 1) [X - 1, 2; X + 1, 2] True 1
We now translate $SL2 \leftarrow RLw \leftrightarrow Ecf$.
''' SL2 Matrices, SL2q Matrices, RL words, Euclidean continued fractions '''
''' (Beware that by convention all euclidean periods start with the R exponent) '''
def SL2_of_RLw(word):
L1 = pari("[1,0;1,1]")
R1 = pari("[1,1;0,1]")
mat = pari("[1,0;0,1]")
for C in word:
if C=='R':
mat=mat*R1
elif C=='L':
mat=mat*L1
else:
raise Exception("Not an RLw as it contains {} of type {}".format(C,type(C)))
return(mat)
def SL2q_of_RLw(word):
L1 = pari("[q,0;1,1/q]")
R1 = pari("[q,1;0,1/q]")
mat = pari("[1,0;0,1]")
for C in word:
if C=='R':
mat=mat*R1
elif C=='L':
mat=mat*L1
else:
raise Exception("Not an RLw as it contains {} of type {}".format(C,type(C)))
return(mat)
def SL2_of_Ecf(ecf):
L1 = pari("[1,0;1,1]")
R1 = pari("[1,1;0,1]")
mat = pari("[1,0;0,1]")
for k,n in enumerate(ecf):
if k%2==0 :
mat=mat*(R1**n)
if k%2==1 :
mat=mat*(L1**n)
return(mat)
def SL2q_of_Ecf(ecf):
L1 = pari("[q,0;1,1/q]")
R1 = pari("[q,1;0,1/q]")
mat = pari("[1,0;0,1]")
for k,n in enumerate(ecf):
if k%2==0 :
mat=mat*(R1**n)
if k%2==1 :
mat=mat*(L1**n)
return(mat)
def RLw_of_Ecf(ecf):
word = ''
for k,n in enumerate(ecf) :
if k%2==0:
word+='R'*n
elif k%2==1:
word+='L'*n
return(word)
def Ecf_of_RLw(word):
if not word:
return([])
first_letter = word[0]
current_letter = word[0]
exponents = [0]
if word[0]=='L':
exponents+=[0]
for c in word:
if c == current_letter:
exponents[-1] += 1
else:
current_letter = c
exponents.append(1)
return exponents
'''Some Tests'''
print(RLw_of_Ecf([1,2,1,1,2,2,2,1,1,2,1,1,2,2,2,1,1,2,1]))
print(Ecf_of_RLw(''), Ecf_of_RLw('R'), Ecf_of_RLw('L'))
print(Ecf_of_RLw('RL'), Ecf_of_RLw('LR'), Ecf_of_RLw('LRLLRL'))
print(SL2_of_RLw('RLLRLRRLLRRLRLLRLRRLLRRLRLLR'))
print(RLw_of_Ecf([1,3,2,1,3]))
RLLRLRRLLRRLRLLRLRRLLRRLRLLR [] [1] [0, 1] [1, 1] [0, 1, 1] [0, 1, 1, 2, 1, 1] [144075, 199796; 103894, 144075] RLLLRRLRRR
Finally we translate $Ecf \leftarrow Qfb$, first extracting the first root of a Qfb to compute its continued fraction and find the corresponding Ecf by inspection, and then using the Conway river function relying on the systematic reduction of quadratic forms by Lagrange.
def exact_firoot_Qfb(Q):
l = pari.component(Q,1)
m = pari.component(Q,2)
r = pari.component(Q,3)
f = pari("{}*x^2+{}*x+{}".format(l,m,r))
Delta = pari.poldisc(f)
# w = (beta+sqrt(Delta))/2 with beta = 0,1 = Delta mod 2
w = pari.quadgen(Delta)
if pari.Mod(Delta,4) == 0 :
root = 2*w
elif pari.Mod(Delta,4) == 1 :
root = 2*w-1
phi = (-m+root)/(2*l)
return phi
# Remark : the dicriminant of the field Q(sqrt(Delta))
# fundisc = pari.coredisc(Delta)
# but we don't care in so far as we compute with Delta in O_\delta
def approx_firoot_Qfb(Q):
l = pari.component(Q,1)
m = pari.component(Q,2)
r = pari.component(Q,3)
f = pari("{}*x^2+{}*x+{}".format(l,m,r))
phi = pari.polroots(f)
phi0, phi1 = phi[0].real(), phi[1].real()
if l>0 :
return pari.max(phi0, phi1)
elif l<0 :
return pari.min(phi0, phi1)
'''Some tests'''
Q1 = pari.Qfb(-11, 71, -66)
print(exact_firoot_Qfb(Q1))
print(exact_firoot_Qfb(Q1)*1.)
print(approx_firoot_Qfb(Q1))
print(pari.contfrac(approx_firoot_Qfb(Q1)))
36/11 - 1/11*w 1.12601375794069 1.12601375794069 [1, 7, 1, 14, 1, 1, 6, 11, 2, 2, 11, 6, 1, 1, 14, 1, 7]
def indiQuad(disc):
ClDisc = pari.quadclassunit(disc) #print('Structure = \t', ClDisc, '\n')
if ClDisc[0]==1:
print("Principal ideal domain")
return([(),()])
factorders = ClDisc[1]
generators = ClDisc[2]
principal = pari.qfbpow(generators[0], 0)
#indices = [()] #neutral
#quadClasses = [principal]
indiQuad = [((),principal)]
for factor in range(len(factorders)):
order = factorders[factor]
generator = generators[factor]
#indices = [index+(exponent,) for index in indices for exponent in range(order)]
#quadClasses = [pari.qfbcomp(quadclass, pari.qfbpow(generator, exponent))\
# for quadclass in quadClasses for exponent in range(order)]
indiQuad = [(indi+(exponent,), pari.qfbred(pari.qfbcomp(quad, pari.qfbpow(generator, exponent)))) \
for (indi, quad) in indiQuad for exponent in range(order)]
return(indiQuad)
indiQuad(1596)
[((0, 0), Qfb(1, 38, -38)), ((0, 1), Qfb(7, 28, -29)), ((1, 0), Qfb(17, 24, -15)), ((1, 1), Qfb(-10, 26, 23)), ((2, 0), Qfb(-3, 36, 25)), ((2, 1), Qfb(-2, 38, 19)), ((3, 0), Qfb(-15, 24, 17)), ((3, 1), Qfb(11, 32, -13))]
We collected the following list of discriminants with interesting class groups by inspection, and encoded their class groups as tables of Ecf (also computed by inspection, ie without the River, but checked).
perioDisc = dict()
############ CYCLIC GROUPS [2] ############
###### CYCLIC GROUPS [2] ######
perioDisc[60] = [[6, 1], [3,2]]
perioDisc[40] = [[6, 6], [2, 1, 1, 2, 1, 1]]
###### CYCLIC GROUPS [3] ######
perioDisc[316] = [[7, 1, 16, 1], [1, 1, 5, 3, 2, 1], [3, 5, 1, 1, 1, 2]]
perioDisc[229] = [[15,15], [2, 4, 1, 2, 4, 1], [2, 1, 4, 2, 1, 4]]
###### CYCLIC GROUPS [4] ######
perioDisc[876] = [[3, 1, 28, 1], [1, 3, 1, 2, 5, 1], [1, 13, 1, 8], [5, 2, 1, 3, 1, 1]]
perioDisc[145] = [[1, 11, 1, 1, 11, 1], [3, 5, 1, 3, 5, 1],
[1, 1, 1, 2, 2, 1, 1, 1, 2, 2], [3, 1, 5, 3, 1, 5]]
perioDisc[8088] = [[88, 1, 28, 1],[1, 4, 2, 2, 3, 1, 2, 7],
[2, 44, 2, 14],[2, 4, 1, 7, 2, 1, 3, 2]]
###### CYCLIC GROUPS [5] ######
perioDisc[1756] = [[19, 1, 40, 1], [1, 1, 6, 3, 13, 1], [1, 2, 3, 1, 3, 1, 7, 1],
[1, 3, 1, 3, 2, 1, 1, 7], [3, 6, 1, 1, 1, 13]]
perioDisc[401] = [[1, 19, 1, 1, 19, 1], [1, 2, 4, 1, 1, 1, 2, 4, 1, 1], [1, 3, 9, 1, 3, 9],
[1, 9, 3, 1, 9, 3], [1, 1, 4, 2, 1, 1, 1, 4, 2, 1]]
###### CYCLIC GROUPS [6] ######
perioDisc[1708] = [[1, 1, 40, 1], [1, 1, 1, 1, 3, 6],
[4, 13, 1, 1], [4, 1, 19, 1],
[1, 13, 4, 1], [3, 1, 1, 1, 1, 6]]
perioDisc[1384] = [[1, 1, 1, 36, 1, 1, 1, 1, 36, 1], [6, 1, 11, 1, 1, 6, 1, 11, 1, 1],
[1, 5, 2, 3, 3, 1, 5, 2, 3, 3], [3, 18, 3, 3, 18, 3],
[5, 1, 3, 3, 2, 5, 1, 3, 3, 2], [1, 6, 1, 1, 11, 1, 6, 1, 1, 11]]
###### CYCLIC GROUP [7] ######
perioDisc[4348] = [[31, 1, 64, 1],
[1, 1, 10, 3, 21,1],
[3, 9, 7, 4, 1, 1],
[5, 3, 1, 2, 2, 1, 1, 1, 2, 1],
[1, 1, 1, 2, 2, 1, 3, 5, 1, 2],
[9, 3, 1, 1, 4, 7],
[1, 1, 1, 21, 3, 10]]
perioDisc[577] = [[1, 23, 1, 1, 23, 1],
[11, 3, 1, 11, 3, 1], [1, 5, 7, 1, 5, 7],
[1, 3, 2, 2, 1, 1, 3, 2, 2, 1], [1, 2, 2, 3, 1, 1, 2, 2, 3, 1],
[7, 5, 1, 7, 5, 1], [1, 3, 11, 1, 3, 11]]
############ NON CYCLIC ############
###### NON CYCLIC GROUP [2,2] ######
perioDisc[780] = [[26, 1], [1, 4, 1, 3],
[1, 8, 1, 1], [13, 2]]
perioDisc[520] = [[2, 22, 2, 2, 22, 2], [7, 7, 2, 7, 7, 2],
[1, 3, 4, 3, 1, 1, 3, 4, 3, 1], [2, 2, 1, 10, 1, 2, 2, 1, 10, 1]]
###### NON CYCLIC GROUP [2,4] ######
perioDisc[1596] = [[38, 1], [19, 2],
[3, 1, 2, 3], [7, 2, 1, 1],
[1, 12, 1, 1], [1, 4, 1, 5],
[3, 3, 2, 1], [7, 1, 1, 2]]
perioDisc[1768] = [[42, 42], [1, 1, 20, 1, 1, 20],
[2, 13, 1, 2, 13,1], [1, 5, 6, 1, 5, 6],
[2, 4, 4, 2, 4, 4], [2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1],
[2, 1, 13, 2, 1, 13], [6, 5, 1, 6, 5, 1]]
print(perioDisc.keys())
dict_keys([60, 40, 316, 229, 876, 145, 8088, 1756, 401, 1708, 1384, 4348, 577, 780, 520, 1596, 1768])
'''List of circular shifts and Lyndon representative (maximal representative, to have uniqueness)'''
def list_of_circular_shifts(word):
n = len(word)
return ["".join([word[i - j] for i in range(n)]) for j in range(n,0,-1)]
def lyndon_of_word(cycle, comp = max):
if cycle == '':
return ''
return comp(list_of_circular_shifts(cycle))
wA = 'RLRLRLRLRLRLRRRRL'
lyndon_of_word(wA), list_of_circular_shifts(wA),
('RRRRLRLRLRLRLRLRL', ['RLRLRLRLRLRLRRRRL', 'LRLRLRLRLRLRRRRLR', 'RLRLRLRLRLRRRRLRL', 'LRLRLRLRLRRRRLRLR', 'RLRLRLRLRRRRLRLRL', 'LRLRLRLRRRRLRLRLR', 'RLRLRLRRRRLRLRLRL', 'LRLRLRRRRLRLRLRLR', 'RLRLRRRRLRLRLRLRL', 'LRLRRRRLRLRLRLRLR', 'RLRRRRLRLRLRLRLRL', 'LRRRRLRLRLRLRLRLR', 'RRRRLRLRLRLRLRLRL', 'RRRLRLRLRLRLRLRLR', 'RRLRLRLRLRLRLRLRR', 'RLRLRLRLRLRLRLRRR', 'LRLRLRLRLRLRLRRRR'])
def Rad_RLw(word):
return word.count('R')-word.count('L')
def Rad_Ecf(ecf):
numR = sum([r for r in ecf[0::2]])
numL = sum([r for r in ecf[1::2]])
return numR-numL
print(Rad_RLw('LRRLLLRLRLRLRRRRLRRL'))
print(Rad_Ecf([0,1,2,3]))
2 -2
def transpose_RLw(word):
"""
transpose_RLw : str('RLL') --> str('RRL')
"""
wordPR = word.replace('L','P')
wordPL = wordPR.replace('R','L')
wordLR = wordPL.replace('P','R')
return wordLR[::-1]
def transpose_Ecf(ecf):
if len(ecf)%2==1:
raise Exception("Ecf of odd lenght")
return ecf[::-1]
def conJ_RLw(word):
"""
The J conjugation on words exchangies R and L
conJ_RLw : str('RLL') --> str('LRR')
"""
wordPR = word.replace('L','P')
wordPL = wordPR.replace('R','L')
wordLR = wordPL.replace('P','R')
return wordLR
def conJ_Ecf(ecf):
if len(ecf)%2==1:
raise Exception("Ecf of odd length")
return (ecf[1:]+ecf[0:1])
"""
def conJ_RLw(word):
to_return = ""
for c in word:
if c == 'L':
to_return += 'R'
else:
to_return += 'L'
return to_return
"""
def is_symmetric(word):
return lyndon_of_word(word) == lyndon_of_word(transpose_RLw(word))
def is_inert(word):
return lyndon_of_word(word) == lyndon_of_word(conJ_RLw(word))
def is_reciprocal(word):
return lyndon_of_word(word) == lyndon_of_word(transpose_RLw(conJ_RLw(word)))
is_symmetric('LRRLRLLRLRR'), is_inert('LRRLRLLRLRR'), is_reciprocal('LRRLRLLRLRR')
(False, False, True)
The following functions apply to words on any alphabet whose elements are linearly ordered.
def orderlex(wa, wb, ka=0, kb=0):
""" lexicographic order on infinite words, returns :
-1 if the ka-th shift of wA^infty is smaller than the kB-th shift of wB^infty,
=0 if the ka-th shift of wA^infty is equal to the kB-th shift of wB^infty,
+1 if the ka-th shift of wA^infty is larger than the kB-th shift of wB^infty
(this can be determined by looking only length(l1)+length(l2) letters
since wa^infty = wb^infty iff wa.wb = wb.wb).
"""
k = 0
while( (wa[(k+ka)%len(wa)] == wb[(k+kb)%len(wb)]) & (k <= (len(wa)+len(wb))) ):
k+=1
if wa[(k+ka)%len(wa)] < wb[(k+kb)%len(wb)]:
return -1
if wa[(k+ka)%len(wa)] > wb[(k+kb)%len(wb)]:
return 1
if wa[(k+ka)%len(wa)] == wb[(k+kb)%len(wb)]:
return 0
def cross_RLw(wa, wb, ka=0, kb=0):
"""symplectic intersection of words RLw provided last letters are distinct"""
if (wa[(ka-1)%len(wa)] < wb[(kb-1)%len(wb)]) & (orderlex(wa,wb,ka,kb) == +1):
return -1
if (wa[(ka-1)%len(wa)] > wb[(kb-1)%len(wb)]) & (orderlex(wa,wb,ka,kb) == -1):
return +1
return 0
def link_RLw(wa, wb):
'''Computes the sum of abs(cross_RLw(wA,wB))) over all pairs of cyclic representatives'''
c = 0
for ka in range(len(wa)):
for kb in range(len(wb)):
if (wa[(ka-1)%len(wa)] < wb[(kb-1)%len(wb)]) & (orderlex(wa,wb,ka,kb) == +1):
c+=1
if (wa[(ka-1)%len(wa)] > wb[(kb-1)%len(wb)]) & (orderlex(wa,wb,ka,kb) == -1):
c+=1
return c//2
def half_inter_RLw(wA,wB):
""" This returns half the geometric intersection number.
Geometric intersection is even for loops in a spherical orbifold. """
wBT = transpose_RLw(wB)
return link_RLw(wA,wB)+link_RLw(wA,wBT)
def coboundary_link_RLw(wA,wB,wC):
return link_RLw(wA,wB)+link_RLw(wA,wC)-link_RLw(wA, wB+wC)
def cosign_sum_RLw(wA,wB):
wBT = transpose_RLw(wB)
return link_RLw(wA,wB)-link_RLw(wA,wBT)
def cosign_cocycle_RLw(wA,wB,wC):
return cosign_sum_RLw(wA,wB)+cosign_sum_RLw(wA,wC)-cosign_sum_RLw(wA, wB+wC)
def link_homology_Rad_RLw(wA,wB):
return link_RLw(wA,wB)-Rad_RLw(wA)*Rad_RLw(wB)+6*Rad_RLw(wA)*Rad_RLw(wB)
print(link_RLw('RLL','RLL'))
print(link_RLw('RLL','RRL'))
print(link_RLw('RLLL','RLLL'))
print(link_RLw('RLLL','RRRL'))
2 1 3 1
a='RLLRL'
x='RLLLR'
y='RLLRL'
print(link_RLw(a,x), half_inter_RLw(a,x), cosign_sum_RLw(a,x), '\n')
print(link_RLw(a,y), half_inter_RLw(a,y), cosign_sum_RLw(a,y), '\n')
print(link_RLw(x,y), half_inter_RLw(x,y), cosign_sum_RLw(x,y), '\n')
print(cosign_sum_RLw(x,y))
print(cosign_cocycle_RLw(a,x,y))
print(coboundary_link_RLw(a,x,y))
5 9 1 6 10 2 5 9 1 1 0 0
a = 'LLRLRRLRRLRLLRL'
b = 'RLLRLLLLLRRRRLLLRLRLR'
c = 'LLLLLRLLLRLLLLLRLRLRL'
RbL = 'R'+b+'L'
LbR = 'L'+b+'R'
LbL = 'L'+b+'L'
RbR = 'R'+b+'R'
RcL = 'R'+c+'L'
LcR = 'L'+c+'R'
LcL = 'L'+c+'L'
RcR = 'R'+c+'R'
print(coboundary_link_RLw(a,RbL,RcR), coboundary_link_RLw(a,RbR,LcR), \
coboundary_link_RLw(a,LbL,LcL), coboundary_link_RLw(a,RbR,RcR), )
print('\n By appropriate choices of a,b,c, we can find non vanishing of any of the following quantities, \n \
are there is always at least one that must vanish ? which one depending on the cross and cosign ?' )
print(coboundary_link_RLw(a,RbL,RcL), coboundary_link_RLw(a,RbL,LcR), \
coboundary_link_RLw(a,RbL,LcL), coboundary_link_RLw(a,RbL,RcR), )
print(coboundary_link_RLw(a,LbR,RcL), coboundary_link_RLw(a,LbR,LcR), \
coboundary_link_RLw(a,LbR,LcL), coboundary_link_RLw(a,LbR,RcR), )
print(coboundary_link_RLw(a,LbL,RcL), coboundary_link_RLw(a,LbL,LcR), \
coboundary_link_RLw(a,LbL,LcL), coboundary_link_RLw(a,LbL,RcR), )
print(coboundary_link_RLw(a,RbR,RcL), coboundary_link_RLw(a,RbR,LcR), \
coboundary_link_RLw(a,RbR,LcL), coboundary_link_RLw(a,RbR,RcR), )
2 -3 -1 -1 By appropriate choices of a,b,c, we can find non vanishing of any of the following quantities, are there is always at least one that must vanish ? which one depending on the cross and cosign ? -1 5 -2 2 2 -1 -4 1 0 2 -1 -1 -4 -3 -10 -1
def link_Ecf(ecfA,ecfB):
RLwA = RLw_of_Ecf(ecfA)
RLwB = RLw_of_Ecf(ecfB)
return link_RLw(RLwA, RLwB)
def half_inter_Ecf(ecfA,ecfB):
RLwA = RLw_of_Ecf(ecfA)
RLwB = RLw_of_Ecf(ecfB)
RLwBT = transpose_RLw(RLwB)
return link_RLw(RLwA,RLwB)+link_RLw(RLwA,RLwBT)
def coboundary_link_Ecf(ecfA,ecfB,ecfC):
RLwA = RLw_of_Ecf(ecfA)
RLwB = RLw_of_Ecf(ecfB)
RLwC = RLw_of_Ecf(ecfC)
return coboundary_link_RLw(RLwA,RLwB,RLwC)
def cosign_sum_Ecf(ecfA,ecfB):
RLwA = RLw_of_Ecf(ecfA)
RLwB = RLw_of_Ecf(ecfB)
RLwBT = transpose_RLw(RLwB)
return link_RLw(RLwA,RLwB)-link_RLw(RLwA,RLwBT)
def cosign_cocycle_Ecf(ecfA,ecfB,ecfC):
RLwA = RLw_of_Ecf(ecfA)
RLwB = RLw_of_Ecf(ecfB)
RLwC = RLw_of_Ecf(ecfC)
return cosign_cocycle_RLw(RLwA,RLwB,RLwC)
def link_homology_Rad_Ecf(ecfA,ecfB):
RLwA = RLw_of_Ecf(ecfA)
RLwB = RLw_of_Ecf(ecfB)
return link_RLw(RLwA,RLwB)-Rad_RLw(RLwA)*Rad_RLw(RLwB)
p1 = [2,1,1,2,1,9]
p2 = [2,1,1,5]
print(link_Ecf(p1,p2), half_inter_Ecf(p1,p2), cosign_sum_Ecf(p1,p2), '\n')
p3 = [2,4,5,3]
print(link_Ecf(p3,p3), half_inter_Ecf(p3,p3), cosign_sum_Ecf(p3,p3), '\n')
print(cosign_sum_Ecf(p1,p2))
print(cosign_cocycle_Ecf(p1,p2,p3), cosign_cocycle_Ecf(p1,p2,p3), '\n')
aR=[1,2,42,1]
aL=[0]+aR
xR=[1,2,1,4,2,1]
xL=[0]+xR
yR=[1,1,1,2,3,4,5,8]
yL=[0]+yR
print(coboundary_link_Ecf(aL,xL,yL), coboundary_link_Ecf(aR,yL,yL))
print(coboundary_link_Ecf(aL,xL,yR), coboundary_link_Ecf(aR,xL,yR))
print(coboundary_link_Ecf(aL,xR,yL), coboundary_link_Ecf(aR,xR,yL))
print(coboundary_link_Ecf(aL,xR,yR), coboundary_link_Ecf(aR,xR,yR))
14 24 4 21 41 1 4 0 0 0 0 0 2 2 0 0 0
# A = [1,2,3,1,1,2,3,1,2,1]
# B = [1,2,5,2,1,1,2,1,2,3]
# A = [1,2,3,1,1,2,3,13]
# B = [1,2,5,2,1,1,2,12]
A = [1,2,3,1,8,2,3,1]
B = [1,2,5,2,9,1,2,9]
AJ = conJ_Ecf(A)
BJ = conJ_Ecf(B)
AT = transpose_Ecf(A)
BT = transpose_Ecf(B)
print(A,B, '\n', AT,BT, '\n', AJ,BJ)
print(link_Ecf(A,B), cosign_sum_Ecf(A,B), half_inter_Ecf(A,B))
# print(link_Ecf(A,BT), cosign_sum(A,BT), halfinter_Ecf(A,BT))
print(link_Ecf(A,BJ), cosign_sum_Ecf(A,BJ), half_inter_Ecf(A,BJ))
print(link_Ecf(A,B)-Rad_Ecf(A)*Rad_Ecf(B))
# print(Rad_Ecf(A), Rad_Ecf(B), Rad_Ecf(A)*Rad_Ecf(B))
[1, 2, 3, 1, 8, 2, 3, 1] [1, 2, 5, 2, 9, 1, 2, 9] [1, 3, 2, 8, 1, 3, 2, 1] [9, 2, 1, 9, 2, 5, 2, 1] [2, 3, 1, 8, 2, 3, 1, 1] [2, 5, 2, 9, 1, 2, 9, 1] 50 6 94 44 -5 93 23
help(pari.matrix)
Help on built-in function matrix: matrix(...) method of cypari._pari.Pari instance matrix(long m, long n, entries=None): Create and return the m x n PARI matrix with given list of entries. Examples: >>> from cypari import pari >>> pari.matrix(3, 3, range(9)) [0, 1, 2; 3, 4, 5; 6, 7, 8]
def bilinear_matrix(function_of_periods, sequence_of_periods):
size = len(sequence_of_periods)
bilist = []
bil_mat = [[0 for i in sequence_of_periods] for j in sequence_of_periods]
for i, p1 in enumerate(sequence_of_periods):
for j, p2 in enumerate(sequence_of_periods):
bil_mat[i][j]=function_of_periods(p1,p2)
bilist.append(function_of_periods(p1,p2))
print(bil_mat[i])
bil_mat_pari = pari.matrix(size, size, bilist)
print(bil_mat_pari.matdet())
# return bil_mat,
disc = 1596
modulus = 5
print('\n', pari.factor(disc), '\n')
bilinear_matrix(cosign_sum_Ecf, perioDisc[disc])
print('\n', modulus, (pari.factor(disc)[:1])%modulus, '\n')
bilinear_matrix(lambda x,y : cosign_sum_Ecf(x,y)%modulus, perioDisc[disc])
[2, 2; 3, 1; 7, 1; 19, 1] [37, 17, 1, 5, -11, -7, 1, 5] [17, 17, 1, 5, -11, -7, 1, 5] [1, 1, 1, 1, -2, -2, 1, 1] [5, 5, 1, 5, -5, -7, 1, 5] [-11, -11, -2, -5, 12, 9, -2, -5] [-7, -7, -2, -7, 9, 14, -2, -7] [1, 1, 1, 1, -2, -2, 1, 1] [5, 5, 1, 5, -5, -7, 1, 5] 0 5 [[2, 3, 2, 4]~] [2, 2, 1, 0, 4, 3, 1, 0] [2, 2, 1, 0, 4, 3, 1, 0] [1, 1, 1, 1, 3, 3, 1, 1] [0, 0, 1, 0, 0, 3, 1, 0] [4, 4, 3, 0, 2, 4, 3, 0] [3, 3, 3, 3, 4, 4, 3, 3] [1, 1, 1, 1, 3, 3, 1, 1] [0, 0, 1, 0, 0, 3, 1, 0] 0
print(perioDisc.keys())
disc = 876
modulus = 3
print('\n', pari.factor(disc), '\n')
bilinear_matrix(link_homology_Rad_Ecf, perioDisc[disc])
print('\n', modulus, (pari.factor(disc)[:1])%modulus, '\n')
bilinear_matrix(lambda x,y : link_homology_Rad_Ecf(x,y)%modulus, perioDisc[disc])
dict_keys([60, 40, 316, 229, 876, 145, 8088, 1756, 401, 1708, 1384, 4348, 577, 780, 520, 1596, 1768]) [2, 2; 3, 1; 73, 1] [-803, -16, 555, -16] [-16, 19, 31, 20] [555, 31, -323, 31] [-16, 20, 31, 19] 1289962 3 [[2, 0, 1]~] [1, 2, 0, 2] [2, 1, 1, 2] [0, 1, 1, 1] [2, 2, 1, 1] 7
for d in perioDisc.keys():
print('\n discriminant =', d, ' with factorisation = ', pari.factor(d))
print('cosigns')
bilinear_matrix(cosign_sum_Ecf, perioDisc[d])
print('half-intersections')
bilinear_matrix(half_inter_Ecf, perioDisc[d])
discriminant = 60 with factorisation = [2, 2; 3, 1; 5, 1] cosigns [5, 1] [1, 1] half-intersections [7, 5] [5, 7] discriminant = 40 with factorisation = [2, 3; 5, 1] cosigns [0, 0] [0, 0] half-intersections [22, 16] [16, 26] discriminant = 316 with factorisation = [2, 2; 79, 1] cosigns [34, 6, -6] [6, 4, -4] [-6, -4, 4] half-intersections [42, 26, 26] [26, 40, 40] [26, 40, 40] discriminant = 229 with factorisation = Mat([229, 1]) cosigns [0, 0, 0] [0, -1, 1] [0, 1, -1] half-intersections [58, 28, 28] [28, 47, 47] [28, 47, 47] discriminant = 876 with factorisation = [2, 2; 3, 1; 73, 1] cosigns [34, 1, -25, 1] [1, 2, -2, 2] [-25, -2, 34, -2] [1, 2, -2, 2] half-intersections [42, 25, 33, 25] [25, 38, 26, 40] [33, 26, 42, 26] [25, 40, 26, 38] discriminant = 145 with factorisation = [5, 1; 29, 1] cosigns [0, 0, 0, 0] [0, -1, 0, 1] [0, 0, 0, 0] [0, 1, 0, -1] half-intersections [62, 48, 48, 48] [48, 63, 56, 63] [48, 56, 82, 56] [48, 63, 56, 63] discriminant = 8088 with factorisation = [2, 3; 3, 1; 337, 1] cosigns [169, -12, -93, -12] [-12, 8, 12, 9] [-93, 12, 79, 12] [-12, 9, 12, 8] half-intersections [177, 44, 109, 44] [44, 90, 60, 93] [109, 60, 103, 60] [44, 93, 60, 90] discriminant = 1756 with factorisation = [2, 2; 439, 1] cosigns [94, 30, 18, -18, -30] [30, 23, 16, -16, -23] [18, 16, 19, -19, -16] [-18, -16, -19, 19, 16] [-30, -23, -16, 16, 23] half-intersections [102, 50, 38, 38, 50] [50, 61, 60, 60, 61] [38, 60, 65, 65, 60] [38, 60, 65, 65, 60] [50, 61, 60, 60, 61] discriminant = 401 with factorisation = Mat([401, 1]) cosigns [0, 0, 0, 0, 0] [0, -1, 0, 0, 1] [0, 0, -1, 1, 0] [0, 0, 1, -1, 0] [0, 1, 0, 0, -1] half-intersections [94, 56, 64, 64, 56] [56, 91, 68, 68, 91] [64, 68, 79, 79, 68] [64, 68, 79, 79, 68] [56, 91, 68, 68, 91] discriminant = 1708 with factorisation = [2, 2; 7, 1; 61, 1] cosigns [40, -3, -9, 23, -9, -3] [-3, 3, 3, -5, 2, 3] [-9, 3, 9, -10, 9, 2] [23, -5, -10, 28, -10, -5] [-9, 2, 9, -10, 9, 3] [-3, 3, 2, -5, 3, 3] half-intersections [48, 21, 25, 31, 25, 21] [21, 33, 29, 25, 30, 37] [25, 29, 31, 30, 33, 30] [31, 25, 30, 36, 30, 25] [25, 30, 33, 30, 31, 29] [21, 37, 30, 25, 29, 33] discriminant = 1384 with factorisation = [2, 3; 173, 1] cosigns [0, 0, 0, 0, 0, 0] [0, -1, 0, 0, 0, 1] [0, 0, -1, 0, 1, 0] [0, 0, 0, 0, 0, 0] [0, 0, 1, 0, -1, 0] [0, 1, 0, 0, 0, -1] half-intersections [198, 120, 108, 132, 108, 120] [120, 159, 132, 136, 132, 159] [108, 132, 167, 132, 167, 132] [132, 136, 132, 154, 132, 136] [108, 132, 167, 132, 167, 132] [120, 159, 132, 136, 132, 159] discriminant = 4348 with factorisation = [2, 2; 1087, 1] cosigns [154, 54, -6, 6, -6, 6, -54] [54, 43, -6, 6, -6, 6, -43] [-6, -6, 3, 0, 0, -3, 6] [6, 6, 0, 4, -4, 0, -6] [-6, -6, 0, -4, 4, 0, 6] [6, 6, -3, 0, 0, 3, -6] [-54, -43, 6, -6, 6, -6, 43] half-intersections [162, 74, 50, 38, 38, 50, 74] [74, 81, 70, 68, 68, 70, 81] [50, 70, 81, 80, 80, 81, 70] [38, 68, 80, 92, 92, 80, 68] [38, 68, 80, 92, 92, 80, 68] [50, 70, 81, 80, 80, 81, 70] [74, 81, 70, 68, 68, 70, 81] discriminant = 577 with factorisation = Mat([577, 1]) cosigns [0, 0, 0, 0, 0, 0, 0] [0, -1, 0, 0, 0, 0, 1] [0, 0, -1, 0, 0, 1, 0] [0, 0, 0, -1, 1, 0, 0] [0, 0, 0, 1, -1, 0, 0] [0, 0, 1, 0, 0, -1, 0] [0, 1, 0, 0, 0, 0, -1] half-intersections [110, 72, 64, 56, 56, 64, 72] [72, 87, 80, 72, 72, 80, 87] [64, 80, 95, 72, 72, 95, 80] [56, 72, 72, 107, 107, 72, 72] [56, 72, 72, 107, 107, 72, 72] [64, 80, 95, 72, 72, 95, 80] [72, 87, 80, 72, 72, 80, 87] discriminant = 780 with factorisation = [2, 2; 3, 1; 5, 1; 13, 1] cosigns [25, -5, -7, 11] [-5, 10, 7, -5] [-7, 7, 8, -7] [11, -5, -7, 11] half-intersections [27, 9, 11, 15] [9, 18, 15, 13] [11, 15, 16, 15] [15, 13, 15, 17] discriminant = 520 with factorisation = [2, 3; 5, 1; 13, 1] cosigns [0, 0, 0, 0] [0, 0, 0, 0] [0, 0, 0, 0] [0, 0, 0, 0] half-intersections [138, 100, 96, 108] [100, 138, 116, 116] [96, 116, 150, 120] [108, 116, 120, 126] discriminant = 1596 with factorisation = [2, 2; 3, 1; 7, 1; 19, 1] cosigns [37, 17, 1, 5, -11, -7, 1, 5] [17, 17, 1, 5, -11, -7, 1, 5] [1, 1, 1, 1, -2, -2, 1, 1] [5, 5, 1, 5, -5, -7, 1, 5] [-11, -11, -2, -5, 12, 9, -2, -5] [-7, -7, -2, -7, 9, 14, -2, -7] [1, 1, 1, 1, -2, -2, 1, 1] [5, 5, 1, 5, -5, -7, 1, 5] half-intersections [39, 21, 9, 11, 15, 11, 9, 11] [21, 23, 13, 15, 19, 15, 13, 15] [9, 13, 23, 19, 16, 18, 25, 19] [11, 15, 19, 19, 17, 19, 19, 21] [15, 19, 16, 17, 20, 17, 16, 17] [11, 15, 18, 19, 17, 22, 18, 19] [9, 13, 25, 19, 16, 18, 23, 19] [11, 15, 19, 21, 17, 19, 19, 19] discriminant = 1768 with factorisation = [2, 3; 13, 1; 17, 1] cosigns [0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0] [0, 0, -1, 0, 0, 0, 1, 0] [0, 0, 0, -1, 0, 0, 0, 1] [0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 0, 0, 0, 0, 0, 0] [0, 0, 1, 0, 0, 0, -1, 0] [0, 0, 0, 1, 0, 0, 0, -1] half-intersections [166, 88, 64, 48, 40, 32, 64, 48] [88, 98, 76, 60, 52, 60, 76, 60] [64, 76, 83, 68, 64, 64, 83, 68] [48, 60, 68, 91, 80, 64, 68, 91] [40, 52, 64, 80, 90, 92, 64, 80] [32, 60, 64, 64, 92, 114, 64, 64] [64, 76, 83, 68, 64, 64, 83, 68] [48, 60, 68, 91, 80, 64, 68, 91]
Be carfull not to try enl(w1,w2) on words of lenth > 12, it is very slow and serves just as a verification.
def linking_patterns(max_word_length, current_pair=('LR', 'RL')):
""" Returns the word base for the computation of enl.
# The set of pairs form a binary tree which we fill in à la Pascal
# The root pair is ('LR','RL')
# The pairs to the extreme left are ('Ln R', 'R Ln')
# The pairs on the extreme right are ('L Rn', 'Rn L')
# The children of (G, D) are
# to the left (GP, GQ) with GP=G[:-1]+'LR' (on enlève 'R' on rajoute 'LR') and GQ=D+'L'
# to the right (DP, DQ) with DP=G+'R' and DQ=D[:-1]+'RL' (on enlève 'L' on rajoute 'RL')
# Note the properties : 'G' ends with 'R' and 'D' ends with 'L' are preserved
# which is why G[:-1] = G - 'R' and D[:-1] = D - 'L'
"""
if len(current_pair[0]) > max_word_length:
return []
pair_left = current_pair[0][:-1]+'LR', current_pair[1]+'L'
pair_right = current_pair[0]+'R', current_pair[1][:-1]+'RL'
return [current_pair] + linking_patterns(max_word_length, pair_left) +\
linking_patterns(max_word_length, pair_right)
def occ(P,A):
# Returns the number of times P appears at the begining of circular shifts of A.
shifts = list_of_circular_shifts(A)
counter = 0
n,l = len(P), len(A)
for shift in shifts:
power = shift + shift * (n//l)
if power[:n] == P:
counter += 1
return counter
def scal_PQ(P,Q,A,B):
return (occ(P,A)*occ(Q,B)+ occ(P,B)*occ(Q,A))
def enl(A,B):
# Returns the enl metric on the words A and B in the L/T alphabet.
patterns = linking_patterns(len(A)+len(B)+1)
return sum([scal_PQ(P,Q,A,B) for P,Q in patterns])//2
linking_patterns(5)
[('LR', 'RL'), ('LLR', 'RLL'), ('LLLR', 'RLLL'), ('LLLLR', 'RLLLL'), ('LLLRR', 'RLLRL'), ('LLRR', 'RLRL'), ('LLRLR', 'RLRLL'), ('LLRRR', 'RLRRL'), ('LRR', 'RRL'), ('LRLR', 'RRLL'), ('LRLLR', 'RRLLL'), ('LRLRR', 'RRLRL'), ('LRRR', 'RRRL'), ('LRRLR', 'RRRLL'), ('LRRRR', 'RRRRL')]
w1 = 'RLRLL' #'RLRLRLLRR'
w2 = 'RLRLL' #'RLLLRLRR'
print(link_RLw(w1,w2), enl(w1,w2))
6 6
A,B = 'L', 'R'
#A,B = 'LR', 'RL'
U,V = A+B, B+A
W1 = 2*U+V
W2 = 2*V+U
print(W1, W2)
print(link_RLw(W1,2*A+B),link_RLw(W1,2*A+B+B),link_RLw(W1,2*A+B+A))
print(link_RLw(W2,2*A+B),link_RLw(W2,2*A+B+B),link_RLw(W2,2*A+B+A))
print(link_RLw(W1,'RLLRRL'), link_RLw(W2, 'RLLRRL'))
for pattern in linking_patterns(max(len(W1), len(W2))):
if occ(pattern[0], W1) != occ(pattern[0], W2):
print(pattern[0])
print(occ(pattern[0], W1), occ(pattern[0], W2))
print(link_RLw(pattern[0], W1), link_RLw(pattern[0], W2))
if occ(pattern[1], W1) != occ(pattern[1], W2):
print(pattern[1])
print(occ(pattern[1], W1), occ(pattern[1], W2))
print(link_RLw(pattern[1], W1), link_RLw(pattern[1], W2))
LRLRRL RLRLLR 3 5 3 3 5 3 8 7 RLLRL 1 0 6 6 RLLRRL 0 1 8 7 LLRR 0 1 5 5 RLRL 0 1 6 6 LLRLR 1 0 6 6 RLRLL 0 1 6 6 LLRLRR 1 0 7 8 RLRRL 1 0 6 6 LLRRLR 0 1 8 7 RLRRLL 1 0 7 8 LRLR 1 0 6 6 RRLL 1 0 5 5 LRLLR 0 1 6 6 LRLLRR 0 1 8 7 RRLLRL 1 0 7 8 LRLRR 1 0 6 6 RRLRL 0 1 6 6 RRLRLL 0 1 8 7 LRRLR 0 1 6 6 LRRLLR 1 0 7 8
pari.trace(A)
P = pari.numerator(F)
trace = P.eval(1)
pari.poldegree(P)
pari.polroots(P)
pari.poldisc(P)
qId = pari("[t,0;0,1/t]")
qDisc = pari.matdet(mat.subst('q','p^2')-qId)
alext = alex.subst('q^2','-t')
poly = pari('q^2+3')
poly.subst('q',1)
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In [34], line 2 1 pari.trace(A) ----> 2 P = pari.numerator(F) 3 trace = P.eval(1) 4 pari.poldegree(P) NameError: name 'F' is not defined
'''The disc_mat works for matrices in GL(2) and scal_sl2 for all matrices in sl(2)
in each case over any commutative the ring, such as Z or Z[q]
for the cosine we need to be have a preferred sqrt over the ring (implemented in PARI)'''
def disc_mat(M):
return pari.trace(M)**2-4*pari.matdet(M)
def scal_sl2(a,b):
return -pari.trace(a*b)/2
def cosine_sl2(a,b):
'''The minus is because we are dealing with a,b both of negative det'''
return -scal_sl2(a,b)/pari.sqrt(scal_sl2(a,a)*scal_sl2(b,b))
def bir_sl2(a,b):
cab=cosine_sl2(a,b)
if cab == -1:
return(pari('oo'))
return 2/(1+cab)
''' The following functions work for matrices in SL(Z) or SL(Z[q])
for the cosine we have a preferred sqrt ? (implemented in PARI) '''
def cotrace_SL2(A,B):
s = pari.sign((pari.trace(A)*pari.trace(B)).subst('q',1))
return s*(pari.trace(A*B)-pari.trace(A/B))
def cosine_SL2(A,B):
nume = cotrace_SL2(A,B)
deno = pari.sqrt(disc_mat(A)*disc_mat(B))
return nume/deno
def cotrace_RLw(wA,wB):
Aq = SL2_of_RLw(wA)
Bq = SL2_of_RLw(wB)
return cotrace_SL2(Aq,Bq)
def cotrace_q_RLw(wA,wB):
Aq = SL2q_of_RLw(wA)
Bq = SL2q_of_RLw(wB)
return cotrace_SL2(Aq,Bq)
def cosine_q_RLw(wA,wB):
Aq = SL2q_of_RLw(wA)
Bq = SL2q_of_RLw(wB)
nume = cotrace_SL2(A,B)
deno = pari.sqrt(disc_mat(Aq)*disc_mat(Bq))
return nume/deno
'''The following functions apply to pari.Qfb'''
def bir_approx_Qfb(QA,QB):
'''Computes cross-ratio(alpha,alpha',beta,beta')
for alpha beta the first roots of QA QB'''
phiA = exact_firoot_Qfb(QA)
phiB = exact_firoot_Qfb(QB)
phiAconj = pari.norm(phiA)/phiA
phiBconj = pari.norm(phiB)/phiB
nume = 1.*(phiA-phiAconj)*(phiB-phiBconj)
deno = (phiA*1.-phiBconj*1.)*(phiB*1.-phiAconj*1.)
# we may use the function pari.simplify() to simplify the type
# here sending a t_QUAD which is rational to a t_FRAC (or t_INT)
ratio = (nume/deno) #.simplify()
return ratio
def bir_samefield_Qfb(QA,QB):
'''Computes cross-ratio(alpha,alpha',beta,beta')
for alpha beta the first roots of QA QB'''
phiA = exact_firoot_Qfb(QA)
phiB = exact_firoot_Qfb(QB)
phiAconj = pari.norm(phiA)/phiA
phiBconj = pari.norm(phiB)/phiB
nume = (phiA-phiAconj)*(phiB-phiBconj)
deno = (phiA-phiBconj)*(phiB-phiAconj)
# we may use the function pari.simplify() to simplify the type
# here sending a t_QUAD which is rational to a t_FRAC (or t_INT)
ratio = (nume/deno) #.simplify()
return ratio
def birinv_samedisc_Qfb(QA,QB):
'''Computes inverse of the cross-ratio(alpha,alpha',beta,beta')
using the scalar product of the QA QB assuming they have same disc
this is a more restrictive case than same field and may be ignored'''
lA, mA, rA = QA[0], QA[1], QA[2]
lB, mB, rB = QB[0], QB[1], QB[2]
discA = mA**2-4*lA*rA
discB = mB**2-4*lB*rB
if discA == discB:
# invBir = (-(lA*mB-lB*mA)**2 + discA*(lA+lB)**2)/(4*lA*lB*discA)
birinv = (discA+mA*mB-2*(lA*rB+lB*rA))/(2*discA)
return(birinv)
else :
raise Exception('Not same disc')
def cosine_RLw(wA, wB):
A = SL2_of_RLw(wA)
sA = sl2_of_SL2(A)
B = SL2_of_RLw(wB)
sB = sl2_of_SL2(B)
return cosine_sl2(sA,sB)
def bir_approx_RLw(wA, wB):
A = SL2_of_RLw(wA)
sA = sl2_of_SL2(A)
B = SL2_of_RLw(wB)
sB = sl2_of_SL2(B)
return bir_sl2(sA,sB)
def bir_samefield_RLw(wA, wB):
A = SL2_of_RLw(wA)
sA = sl2_of_SL2(A)
QA = Qfb_of_sl2(sA)
B = SL2_of_RLw(wB)
sB = sl2_of_SL2(B)
QB = Qfb_of_sl2(sB)
return bir_samefield_Qfb(QA,QB)
''' Testing that all computations of bir form same disc or same field are consistent : they are !'''
for ecfA in perioDisc[8088]:
for ecfB in perioDisc[8088]:
# if ecfA == ecfB:
# continue
A = SL2_of_Ecf(ecfA)
sA = sl2_of_SL2(A)
QA = Qfb_of_sl2(sA)
B = SL2_of_Ecf(ecfB)
sB = sl2_of_SL2(B)
QB = Qfb_of_sl2(sB)
birSL2 = 2/(1+cosine_SL2(A,B))
birsl2 = bir_sl2(sA,sB)
birqfbsd = 1/birinv_samedisc_Qfb(QA,QB)
birqfbsf = bir_samefield_Qfb(QA,QB)
print('\n', sA, '\t', sB, '\t \n', '\n', birSL2, birsl2, birqfbsf*1., '\t', birqfbsf, birqfbsd)
Aq = SL2q_of_Ecf(ecfA)
Bq = SL2q_of_Ecf(ecfB)
birSL2q = 2/(1+cosine_SL2(Aq,Bq))
print(birSL2q)
[44, 86; 1, -44] [44, 86; 1, -44] 1.00000000000000 1.00000000000000 1.00000000000000 1 1 1 + O(q^16) [44, 86; 1, -44] [36, 11; 66, -36] 0.627025350802388 0.627025350802388 0.627025350802388 8088/12899 8088/12899 1 - q^6 + q^12 + q^14 + O(q^16) [44, 86; 1, -44] [42, 6; 43, -42] 0.706745893044390 0.706745893044390 0.706745893044390 2022/2861 2022/2861 1 - q^8 + q^12 + O(q^16) [44, 86; 1, -44] [30, 33; 34, -30] 0.838917124779587 0.838917124779587 0.838917124779587 8088/9641 8088/9641 1 - q^8 + q^10 + q^12 - 2*q^14 + O(q^16) [36, 11; 66, -36] [44, 86; 1, -44] 0.627025350802388 0.627025350802388 0.627025350802388 8088/12899 8088/12899 1 - q^6 + q^12 + q^14 + O(q^16) [36, 11; 66, -36] [36, 11; 66, -36] 1.00000000000000 1.00000000000000 1.00000000000000 1 1 1 + O(q^16) [36, 11; 66, -36] [42, 6; 43, -42] 1.01902482046113 1.01902482046113 1.01902482046113 8088/7937 8088/7937 1 + O(q^16) [36, 11; 66, -36] [30, 33; 34, -30] 0.923709456372773 0.923709456372773 0.923709456372773 2022/2189 2022/2189 1 - q^8 + q^10 + q^12 - q^14 + O(q^16) [42, 6; 43, -42] [44, 86; 1, -44] 0.706745893044390 0.706745893044390 0.706745893044390 2022/2861 2022/2861 1 - q^8 + q^12 + O(q^16) [42, 6; 43, -42] [36, 11; 66, -36] 1.01902482046113 1.01902482046113 1.01902482046113 8088/7937 8088/7937 1 + O(q^16) [42, 6; 43, -42] [42, 6; 43, -42] 1.00000000000000 1.00000000000000 1.00000000000000 1 1 1 + O(q^16) [42, 6; 43, -42] [30, 33; 34, -30] 0.987907658482961 0.987907658482961 0.987907658482961 2696/2729 2696/2729 1 + O(q^16) [30, 33; 34, -30] [44, 86; 1, -44] 0.838917124779587 0.838917124779587 0.838917124779587 8088/9641 8088/9641 1 - q^8 + q^10 + q^12 - 2*q^14 + O(q^16) [30, 33; 34, -30] [36, 11; 66, -36] 0.923709456372773 0.923709456372773 0.923709456372773 2022/2189 2022/2189 1 - q^8 + q^10 + q^12 - q^14 + O(q^16) [30, 33; 34, -30] [42, 6; 43, -42] 0.987907658482961 0.987907658482961 0.987907658482961 2696/2729 2696/2729 1 + O(q^16) [30, 33; 34, -30] [30, 33; 34, -30] 1.00000000000000 1.00000000000000 1.00000000000000 1 1 1 + O(q^16)
The intersection points of two modular geodesics corresponding to modular conjugacy classes $[A]$ and $[B]$ correspond to the set of all pairs of representatives for the conjugacy classes whose axes have interlaced endpoints modulo simultaneous conjugacy of the pair.
Up to simultaneous conjugacy, we may assume that the intersection happens at the base edge of the trivalent tree and that the representative $A$ is in the Euclidean monoid $PSL(2;N)$ of $R\& L$-words, and that the representative $B$ is either in $PSL(2;N)$ or its transpose inverse $SBS^{-1} = {}^t\!B^{-1}$ is in $PSL(2;N)$. Moreover the intersection is uniquely parametrised when $cross(A,B)\ne 0$ or $cross(A, SBS^{-1})\ne 0$ respectively, which means that their last letters are distinct and ordered oppositely to their futures.
In summary the intersection points are parametrized by the the pairs of RL words (wA, wB) and (wA, wBT), where we are remembering in the latter case that the actual representative is the inverse of wBT, in particular the $\cos(A,SBS^{-1}) = -\cos(A,{}^t\!B)$ and $cross(A,SBS^{-1}) = -cross(A,{}^t\!B)$.
def iter_funcond_cycles_RLw(wa, wb, func = lambda x, y : (x,y), \
cond = lambda wa, wb : cross_RLw(wa, wb)!=0):
'''Generates iterator of func(A,B) over pairs of cyclic representatives with cond(A,B)'''
for ka in range(len(wa)):
for kb in range(len(wb)):
waka = wa[ka:]+wa[:ka]
wbkb = wb[kb:]+wb[:kb]
if cond(waka,wbkb):
yield func(waka,wbkb)
def iter_funcond_inter_RLw(wa, wb, func = lambda x,y, iota : (x,y), \
cond = lambda wa, wb, iota : cross_RLw(wa, wb)!=0):
'''
Generates iterator iterable of func(A,B, iota) with cond(A,B, iota)
over all independant pairs of conj classes that interesect modulo sumplutaneous conjugacy.
We may restrict to those passing through the base edge of the trivalent tree, and choose
the first to be in PSL(2;N) ie an RLw and the other in PSL(2;-N) ie an S(LRw)S^{-1}
'''
wbT = transpose_RLw(wb)
for ka in range(len(wa)):
for kb in range(len(wb)):
waka = wa[ka:]+wa[:ka]
wbkb = wb[kb:]+wb[:kb]
wbTkb = wbT[kb:]+wbT[:kb]
if cond(waka, wbkb, +1):
yield func(waka, wbkb, +1)
if cond(waka, wbTkb, -1):
yield func(waka, wbTkb, -1)
The following examples recalls that $(cross \ne 0) \Rightarrow (cross ratio \ge 1) $ but $(cross \ne 0) \not\Leftarrow (cross ratio \ge 1) $ because :
print(perioDisc[1596], '\n')
wA = RLw_of_Ecf([3,1,2,3])
wB = RLw_of_Ecf([7,2,1,1]) # 19,2
print('\n We see that cross non zero implies bir >= 1 : \n')
func = lambda wa, wb : (bir_samefield_RLw(wa,wb), pari.floor(bir_samefield_RLw(wa,wb)*1.))
print([p for p in iter_funcond_cycles_RLw(wA,wB,func)])
print('\n We compute the cosines at intersection points : \n')
funci = lambda wa, wb, iota : (2/bir_samefield_RLw(wa,wb)-1)*iota
print([p for p in iter_funcond_inter_RLw(wA, wB, funci)])
[[38, 1], [19, 2], [3, 1, 2, 3], [7, 2, 1, 1], [1, 12, 1, 1], [1, 4, 1, 5], [3, 3, 2, 1], [7, 1, 1, 2]] We see that cross non zero implies bir >= 1 : [(1596/1531, 1), (532/417, 1), (1596/871, 1), (1596/391, 4), (532/345, 1), (532/477, 1), (1596/1111, 1), (28/27, 1), (1596/691, 2), (1596/1027, 1), (532/417, 1), (399/187, 2), (1596/1375, 1), (399/283, 1), (532/477, 1), (228/85, 2), (1596/1375, 1), (399/199, 2), (1596/1543, 1), (399/283, 1)] We compute the cosines at intersection points : [-121/399, -17/42, 733/798, 397/798, 151/266, 73/798, -407/798, 79/266, 211/266, 313/798, -683/798, 13/14, -107/798, -1/7, -29/114, 229/798, -11/14, -89/114, -25/399, 151/266, -25/399, 577/798, 167/399, -89/114, -599/798, 211/266, -29/114, 79/266, -1/399, 577/798, -1/399, -611/798, -121/399, -515/798, 745/798, -743/798, -1/7, 167/399]
where $P_n$ often belongs to a familly of orthogonal polynomials like: powers, Legendre, Chebychev,...
and compare with the values of $lk(A,B), cosign(A,B), inter(A,B),...$.
def sum_funchi_inter_RLw(wa, wb, func, chi):
'''
Computes sum of func(A,B, iota)*chi(cross(A,B)) over intersections,
parametrized by pairs of of conj classes that interesect modulo simultaneous conjugacy,
namely (wA,wB) with cross(wA,wB) != 0 and (wA, wBT inverse) with -cross(wA, wBT) != 0
'''
somme = 0
wbT = transpose_RLw(wb)
for ka in range(len(wa)):
for kb in range(len(wb)):
waka = wa[ka:]+wa[:ka]
wbkb = wb[kb:]+wb[:kb]
wbTkb = wbT[kb:]+wbT[:kb]
somme += func(waka, wbkb, +1)*chi(cross_RLw(waka, wbkb))
somme += func(waka, wbTkb, -1)*chi(-cross_RLw(waka, wbTkb))
return somme
def prod_funchi_inter_RLw(wa, wb, func, chi):
'''
Computes prod of func(A,B, iota)**chi(cross(A,B)) over intersections,
parametrized by pairs of of conj classes that interesect modulo simultaneous conjugacy,
namely (wA,wB) with cross(wA,wB) != 0 and (wA, wBT inverse) with -cross(wA, wBT) != 0
'''
produit = 1
wbT = transpose_RLw(wb)
for ka in range(len(wa)):
for kb in range(len(wb)):
waka = wa[ka:]+wa[:ka]
wbkb = wb[kb:]+wb[:kb]
wbTkb = wbT[kb:]+wbT[:kb]
produit *= func(waka, wbkb, +1)**chi(cross_RLw(waka, wbkb))
produit *= func(waka, wbTkb, -1)**chi(-cross_RLw(waka, wbTkb))
return produit
def sum_invBir_chi_RLw(wA,wB,n,chi):
'''Sum of chi(cross(A,B))*(1/bir(A,B))^n'''
discAdiscB = disc_mat(SL2_of_RLw(wA))*disc_mat(SL2_of_RLw(wB))
# delta = pari.sqrt(discAdiscB)
if discAdiscB.issquare():
funci = lambda wa, wb, iota : ((1+iota*(2/bir_samefield_RLw(wa,wb)-1))/2)**n
else :
funci = lambda wa, wb, iota : ((1+iota*(2/bir_approx_RLw(wa,wb)-1))/2)**n
return sum_funchi_inter_RLw(wA, wB, funci, chi)
def prod_invBir_chi_RLw(wA,wB,n,chi):
'''Prod of (1/bir(A,B))^(chi(cross(A,B)).n)'''
discAdiscB = disc_mat(SL2_of_RLw(wA))*disc_mat(SL2_of_RLw(wB))
if discAdiscB.issquare():
funci = lambda wa, wb, iota : ((1+iota*(2/bir_samefield_RLw(wa,wb)-1))/2)**n
else :
funci = lambda wa, wb, iota : ((1+iota*(2/bir_approx_RLw(wa,wb)-1))/2)**n
return prod_funchi_inter_RLw(wA, wB, funci, chi)
ecfA = [3,1,2,3] # [6,1] #
ecfB = [19,2] # [7,2,1,1] # [3,2] #
wA = RLw_of_Ecf(ecfA)
wB = RLw_of_Ecf(ecfB)
wBJ = conJ_RLw(wB)
discAdiscB = disc_mat(SL2_of_RLw(wA))*disc_mat(SL2_of_RLw(wB))
print(discAdiscB, '\n')
print(link_RLw(wA,wB), cosign_sum_RLw(wA,wB), 2*half_inter_RLw(wA,wB), '\t', \
link_RLw(wA,wBJ), cosign_sum_RLw(wA,wBJ), 2*half_inter_RLw(wA,wBJ), '\n')
print(sum_invBir_chi_RLw(wA,wB, 0, lambda x : (x)), \
sum_invBir_chi_RLw(wA,wB, 0, lambda x : abs(x)), '\n',\
sum_invBir_chi_RLw(wA,wB, 1, lambda x : (x)), \
sum_invBir_chi_RLw(wA,wB, 1, lambda x : abs(x)), '\n',\
sum_invBir_chi_RLw(wA,wB, 2, lambda x : (x)), \
sum_invBir_chi_RLw(wA,wB, 2, lambda x : abs(x)), '\n',\
sum_invBir_chi_RLw(wA,wB, 3, lambda x : (x)), \
sum_invBir_chi_RLw(wA,wB, 3, lambda x : abs(x)), '\n', \
sum_invBir_chi_RLw(wA,wB, 4, lambda x : (x)), \
sum_invBir_chi_RLw(wA,wB, 4, lambda x : abs(x)), '\n')
print('\n')
if discAdiscB.issquare():
print(prod_invBir_chi_RLw(wA,wB, 1, lambda x : (x)), '\n', \
pari.factor(pari.simplify(prod_invBir_chi_RLw(wA,wB, 1, lambda x : (x))))[:1], '\n', \
pari.factor(pari.simplify(prod_invBir_chi_RLw(wA,wB, 1, lambda x : (x))))[1:], '\n', \
prod_invBir_chi_RLw(wA,wB, 1, lambda x : abs(x)), '\n', \
pari.factor(pari.simplify(prod_invBir_chi_RLw(wA,wB, 1, lambda x : abs(x))))[:1], '\n', \
pari.factor(pari.simplify(prod_invBir_chi_RLw(wA,wB, 1, lambda x : abs(x))))[1:])
2547216 7 1 26 6 -1 26 0 26 0 5246/399 0 1343507/159201 0 1543225409/254084796 0 1889095198745/405519334416 11202345070866585093794787/14383891192135961400019363 [[3, 11, 17, 23, 29, 53, 59, 79, 151, 167, 191, 331, 379, 751, 991, 1171, 1471]~] [[5, 2, 2, -2, 1, -2, -2, -3, -1, -1, -1, 2, 1, 1, 1, -1, 1]~] 211870827499856154617528286311080757069945692069988796875/1790101910978244237672749753761738423691647995748881939263744114688 [[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 53, 59, 79, 151, 167, 191, 331, 379, 751, 991, 1171, 1471]~] [[-28, -9, 6, -24, 4, 2, 2, -26, 2, 1, 2, 2, 3, 1, 1, 1, 2, 1, 1, 1, 1, 1]~]
def sum_cotrace_chi_RLw(wA,wB,n,chi):
'''Sum of chi(cross(A,B))*( (sign(Tr(A)Tr(B))*(Tr(AB)-Tr(A/B)) )^n'''
funci = lambda wa, wb, iota : (iota*cotrace_RLw(wA,wB))**n
return sum_funchi_inter_RLw(wA, wB, funci, chi)
def sum_cotrace_q_chi_RLw(wA,wB,n,chi):
'''Sum of chi(cross(A,B))*( (sign(Tr(A)Tr(B))*(Tr(AqBq)-Tr(Aq/Bq)) )^n'''
funci = lambda wa, wb, iota : (iota*cotrace_q_RLw(wA,wB))**n
return sum_funchi_inter_RLw(wA, wB, funci, chi)
ecfA, ecfB = [1, 1, 6, 3, 13, 1], [19, 1, 40, 1]
ecfA, ecfB = [1, 1, 6, 3, 13, 1], [1, 2, 3, 1, 3, 1, 7, 1]
ecfA, ecfB = [1, 1, 6, 3, 13, 1], [1, 3, 1, 3, 2, 1, 1, 7]
ecfA, ecfB = [3, 6, 1, 1, 1, 13], [1, 3, 1, 3, 2, 1, 1, 7]
#ecfA = [3,1,2,3] # [6,1] #
#ecfB = [19,2] # [7,2,1,1] # [3,2] #
wA = RLw_of_Ecf(ecfA)
wB = RLw_of_Ecf(ecfB)
wBJ = conJ_RLw(wB)
discAdiscB = disc_mat(SL2_of_RLw(wA))*disc_mat(SL2_of_RLw(wB))
print(discAdiscB, discAdiscB.factor()[:1], '\n')
print(link_RLw(wA,wB), cosign_sum_RLw(wA,wB), 2*half_inter_RLw(wA,wB), '\t', \
link_RLw(wA,wBJ), cosign_sum_RLw(wA,wBJ), 2*half_inter_RLw(wA,wBJ), '\n')
print(sum_cotrace_chi_RLw(wA,wB, 0, lambda x : (x)).factor()[:1], \
sum_cotrace_chi_RLw(wA,wB, 0, lambda x : abs(x)).factor()[:1], '\n',\
sum_cotrace_chi_RLw(wA,wB, 1, lambda x : (x)).factor()[:1], \
sum_cotrace_chi_RLw(wA,wB, 1, lambda x : abs(x)).factor()[:1], '\n',\
sum_cotrace_chi_RLw(wA,wB, 2, lambda x : (x)).factor()[:1], \
sum_cotrace_chi_RLw(wA,wB, 2, lambda x : abs(x)).factor()[:1], '\n',\
sum_cotrace_chi_RLw(wA,wB, 3, lambda x : (x)).factor()[:1], \
sum_cotrace_chi_RLw(wA,wB, 3, lambda x : abs(x)).factor()[:1], '\n', \
sum_cotrace_chi_RLw(wA,wB, 7, lambda x : (x)).factor()[:1], \
sum_cotrace_chi_RLw(wA,wB, 7, lambda x : abs(x)).factor()[:1], '\n')
print(sum_cotrace_q_chi_RLw(wA,wB, 0, lambda x : (x)), \
#sum_cotrace_q_chi_RLw(wA,wB, 0, lambda x : abs(x)), '\n',\
sum_cotrace_q_chi_RLw(wA,wB, 1, lambda x : (x)), \
#sum_cotrace_q_chi_RLw(wA,wB, 1, lambda x : abs(x)), '\n',\
sum_cotrace_q_chi_RLw(wA,wB, 2, lambda x : (x))
#sum_cotrace_q_chi_RLw(wA,wB, 2, lambda x : abs(x)), '\n'
)
599689164816 [[2, 3, 7, 439]~] 38 16 120 22 -17 122 [[0]~] [[2, 3, 5]~] [[0]~] [[2, 3, 5, 7, 167]~] [[0]~] [[2, 3, 5, 7, 167]~] [[0]~] [[2, 3, 5, 7, 167]~] [[0]~] [[2, 3, 5, 7, 167]~] 0 0 0
For prod_invBir_chi_RLw(wA,wB, 1, chi) we observe a lot of simplifications from chi(x)= abs(x) to chi(x)=x, some completely dissapear and the big exponents decrease drastically. For example when $ecfA = [3,1,2,3]$ and $ecfB = [19,2]$ the primes $2,5,13,17$ dissappear.
We also observe that these cross ratios have many small primes, and indeed we expect them to be smaller than the discriminant.
for n in range(6):
print(pari.pollegendre(n),'\t\t\t', pari.polchebyshev(n))
1 1 x x 3/2*x^2 - 1/2 2*x^2 - 1 5/2*x^3 - 3/2*x 4*x^3 - 3*x 35/8*x^4 - 15/4*x^2 + 3/8 8*x^4 - 8*x^2 + 1 63/8*x^5 - 35/4*x^3 + 15/8*x 16*x^5 - 20*x^3 + 5*x
def sum_Power_cos_chi_RLw(wA,wB,n,chi):
'''Sum of chi(cross(A,B)) times (cos(A,B))^n'''
discAdiscB = disc_mat(SL2_of_RLw(wA))*disc_mat(SL2_of_RLw(wB))
if discAdiscB.issquare():
funci = lambda wa, wb, iota : (iota*(2/bir_samefield_RLw(wa,wb)-1))**n
else :
funci = lambda wa, wb, iota : (iota*(2/bir_approx_RLw(wa,wb)-1))**n
#coefnAB = pari.sqrt(discAdiscB)**n*pari(2)**(2*n+1)/pari.binomial(2*n,n)
return sum_funchi_inter_RLw(wA, wB, funci, chi)
def sum_Legendre_cos_chi_RLw(wA,wB,n,chi):
'''Sum of chi(cross(A,B)) times (cos(A,B))^n'''
discAdiscB = disc_mat(SL2_of_RLw(wA))*disc_mat(SL2_of_RLw(wB))
if discAdiscB.issquare() :
funci = lambda wa, wb, iota : pari.pollegendre(n).eval(iota*(2/bir_samefield_RLw(wa,wb)-1))
else :
funci = lambda wa, wb, iota : pari.pollegendre(n).eval(iota*(2/bir_approx_RLw(wa,wb)-1))
#coefnAB = pari.sqrt(discAdiscB)**n*pari(2)**(2*n+1)/pari.binomial(2*n,n)
return sum_funchi_inter_RLw(wA, wB, funci, chi)
def sum_Chebyshev_cos_chi_RLw(wA,wB,n,chi):
'''Sum of chi(cross(A,B)) times (cos(A,B))^n'''
discAdiscB = disc_mat(SL2_of_RLw(wA))*disc_mat(SL2_of_RLw(wB))
if discAdiscB.issquare() :
funci = lambda wa, wb, iota : pari.polchebyshev(n).eval(iota*(2/bir_samefield_RLw(wa,wb)-1))
else :
funci = lambda wa, wb, iota : pari.polchebyshev(n).eval(iota*(2/bir_approx_RLw(wa,wb)-1))
#coefnAB = pari.sqrt(discAdiscB)**n*pari(2)**(2*n+1)/pari.binomial(2*n,n)
return sum_funchi_inter_RLw(wA, wB, funci, chi)
ecfA = [3,1,2,3] #[6,1] #
ecfB = [7,2,1,1] #[3,2] #
wA = RLw_of_Ecf(ecfA)
wB = RLw_of_Ecf(ecfB)
wBJ = conJ_RLw(wB)
print(pari.sqrt(disc_mat(SL2_of_RLw(wA))*disc_mat(SL2_of_RLw(wB))), '\n')
print(link_RLw(wA,wB), cosign_sum_RLw(wA,wB), 2*half_inter_RLw(wA,wB), '\t', \
link_RLw(wA,wBJ), cosign_sum_RLw(wA,wBJ), 2*half_inter_RLw(wA,wBJ), '\n')
print(sum_Power_cos_chi_RLw(wA,wB, 0, lambda x : (x)), \
sum_Power_cos_chi_RLw(wA,wB, 0, lambda x : abs(x)), \
sum_Power_cos_chi_RLw(wA,wB, 1, lambda x : (x)), \
sum_Power_cos_chi_RLw(wA,wB, 1, lambda x : abs(x)), \
sum_Power_cos_chi_RLw(wA,wB, 3, lambda x : (x)), \
sum_Power_cos_chi_RLw(wA,wB, 3, lambda x : abs(x)))
print(sum_Power_cos_chi_RLw(wA,wB, 2, lambda x : (x)), \
sum_Power_cos_chi_RLw(wA,wB, 2, lambda x : abs(x)), \
sum_Power_cos_chi_RLw(wA,wB, 3, lambda x : (x)), \
sum_Power_cos_chi_RLw(wA,wB, 3, lambda x : abs(x)) )
print(sum_Legendre_cos_chi_RLw(wA,wB, 2, lambda x : (x)), \
sum_Legendre_cos_chi_RLw(wA,wB, 2, lambda x : abs(x)), \
sum_Legendre_cos_chi_RLw(wA,wB, 3, lambda x : (x)), \
sum_Legendre_cos_chi_RLw(wA,wB, 3, lambda x : abs(x)) )
print(sum_Chebyshev_cos_chi_RLw(wA,wB, 2, lambda x : (x)), \
sum_Chebyshev_cos_chi_RLw(wA,wB, 2, lambda x : abs(x)), \
sum_Chebyshev_cos_chi_RLw(wA,wB, 3, lambda x : (x)), \
sum_Chebyshev_cos_chi_RLw(wA,wB, 3, lambda x : abs(x)) )
1596.00000000000 10 1 38 9 -1 38 0 38 0 44/57 0 4068889/6686442 0 1966273/159201 0 4068889/6686442 0 -50273/106134 0 4860053/13372884 0 -2117092/159201 0 395582/3343221
print(perioDisc.keys())
print(perioDisc[60])
dict_keys([60, 40, 316, 229, 876, 145, 8088, 1756, 401, 1708, 1384, 4348, 577, 780, 520, 1596, 1768]) [[6, 1], [3, 2]]
We know that loops in a spherical orbifold have trivial algebraic intersection number so : \begin{equation*} \sum_{x} \epsilon_x(A,B) \times \cos_x(A,B)^{0} = 0 \end{equation*}
Since the Poisson structure is trivial (as the character variety has dimension one), we also know that: \begin{equation*} \sum_{x} \epsilon_x(A,B) \times \cos_x(A,B)^{1} = 0 \end{equation*}
Our experiments suggest that we also have: \begin{equation*} \sum_{x} \epsilon_x(A,B) \times \cos_x(A,B)^{3} = 0 \end{equation*}
for ecfA in perioDisc[1756]:
for ecfB in perioDisc[1756]:
wA = RLw_of_Ecf(ecfA)
wB = RLw_of_Ecf(ecfB)
for n in range(8):
s= sum_Power_cos_chi_RLw(wA,wB, n, lambda x : x)
if s*10**10>1:
print(ecfA,ecfB, n, s)
break
print("Done")
[1, 1, 6, 3, 13, 1] [19, 1, 40, 1] 5 867063859200/16305067506199 [1, 1, 6, 3, 13, 1] [1, 2, 3, 1, 3, 1, 7, 1] 5 1939919385600/16305067506199 [1, 1, 6, 3, 13, 1] [1, 3, 1, 3, 2, 1, 1, 7] 5 1939919385600/16305067506199 [1, 2, 3, 1, 3, 1, 7, 1] [19, 1, 40, 1] 5 4149519897600/16305067506199 [1, 2, 3, 1, 3, 1, 7, 1] [1, 1, 6, 3, 13, 1] 7 145398942368265600/3142328914862177479 [1, 2, 3, 1, 3, 1, 7, 1] [3, 6, 1, 1, 1, 13] 7 145398942368265600/3142328914862177479 [1, 3, 1, 3, 2, 1, 1, 7] [19, 1, 40, 1] 5 4149519897600/16305067506199 [1, 3, 1, 3, 2, 1, 1, 7] [1, 1, 6, 3, 13, 1] 7 145398942368265600/3142328914862177479 [1, 3, 1, 3, 2, 1, 1, 7] [3, 6, 1, 1, 1, 13] 7 145398942368265600/3142328914862177479 [3, 6, 1, 1, 1, 13] [19, 1, 40, 1] 5 867063859200/16305067506199 [3, 6, 1, 1, 1, 13] [1, 2, 3, 1, 3, 1, 7, 1] 5 1939919385600/16305067506199 [3, 6, 1, 1, 1, 13] [1, 3, 1, 3, 2, 1, 1, 7] 5 1939919385600/16305067506199 Done