326 lines
11 KiB
Plaintext
326 lines
11 KiB
Plaintext
def Delta(lista,B):
|
|
res=B(1)
|
|
l=copy(lista)[:-1]
|
|
while len(l)>0:
|
|
res=res*B(l)
|
|
l=l[:-1]
|
|
return res
|
|
|
|
def clean_conj(lista,F):
|
|
n=len(lista)
|
|
if n%2==0:
|
|
print "Not conjugate to a generator"
|
|
return None
|
|
m=ZZ((n-1)/2)
|
|
a=lista[m]
|
|
b=lista[m+1:]
|
|
if F(b)*F(lista[:m])!=F(1):
|
|
print "Not conjugate to a generator"
|
|
return None
|
|
return [a,b]
|
|
|
|
def list_of_relations_2(orden0,wiring0):
|
|
wiring=[[B(_[0]),_[1]]for _ in wiring0]
|
|
res1=[]
|
|
trenza=B(1)
|
|
orden=copy(orden0)
|
|
for cruce in wiring:
|
|
u,v=cruce
|
|
orden=(u^-1).permutation()*orden
|
|
trenza=trenza*u
|
|
w=[orden.inverse()(_) for _ in v]
|
|
res1.append([trenza,v,w,orden])
|
|
trw=Delta(w,B)
|
|
trenza=trenza*trw
|
|
orden=trw.permutation().inverse()*orden
|
|
final=[]
|
|
for aa in res1:
|
|
lis=[]
|
|
for i in aa[2]:
|
|
accion=[_.sign()*orden0(_.abs()) for _ in (F([i])*aa[0]^-1).Tietze()]
|
|
listas=clean_conj(accion,F)
|
|
if listas==None:
|
|
print 'Problems'
|
|
return None
|
|
else:
|
|
lis+=[listas]
|
|
datos1=[[_[0] for _ in lis],[_[1] for _ in lis]]
|
|
final+=[datos1]
|
|
return final
|
|
|
|
|
|
def CommProd1(a,l1,F,LR,XX):
|
|
ll1=list(F(l1).Tietze())
|
|
if len(ll1)==0:
|
|
return M(0)
|
|
return XX[a,ll1[0]]+tt([ll1[0]],LR)*CommProd1(a,ll1[1:],F,LR,XX)
|
|
|
|
|
|
def CommCyclic1(L,F,LR,XX,dir='RL'):
|
|
res=[]
|
|
r=len(L[0])
|
|
comb=L[0]
|
|
mn=comb.index(min(comb))
|
|
L1=[v[mn:]+v[:mn] for v in L]
|
|
LF=[F([-u for u in reversed(L1[1][j])]+[L1[0][j]]+L1[1][j]) for j in range(r)]
|
|
for j in range(1,r):
|
|
u=F(L1[1][j])
|
|
if dir=='RL':
|
|
LFp=[_ for _ in reversed(LF[j+1:]+LF[:j])]
|
|
elif dir=='LR':
|
|
LFp=LF[j+1:]+LF[:j]
|
|
w=u*prod(LFp)*u^-1
|
|
res+=[CommProd1(L1[0][j],list(w.Tietze()),F,LR,XX)]
|
|
return res
|
|
|
|
def tt(i,ring):
|
|
return prod([LR.gen(ZZ(j).abs()-1)^(ZZ(j).sign()) for j in i])
|
|
|
|
def MatTrunc(mat):
|
|
A=mat
|
|
m=A.nrows()
|
|
return Matrix(m,[v.truncate(2) for v in A.list()])
|
|
|
|
|
|
def EscalonarM2(matriz,n):
|
|
U=matriz
|
|
U0=Matrix(U.nrows(),[v.constant_coefficient() for v in U.list()])
|
|
A,B=U0.echelon_form(transformation=True)
|
|
U1=B*U
|
|
Apivot=[]
|
|
j=0
|
|
for i in range(A.rank()):
|
|
while A[i,j]==0:
|
|
j=j+1
|
|
Apivot.append(j)
|
|
for i in range(A.rank()):
|
|
j=Apivot[i]
|
|
U1.rescale_row(i,U1[i,j]^-1)
|
|
for k in range(i)+range(i+1,A.nrows()):
|
|
U1.add_multiple_of_row(k,i,-U1[k,j])
|
|
SustNeg=identity_matrix(T0,n*(n-1)/2)
|
|
for i in range(A.rank()):
|
|
for j in range(n*(n-1)/2):
|
|
SustNeg[j,Apivot[i]]=-U1[i,j].truncate(2).polynomial()
|
|
SustNeg=SustNeg.delete_rows(Apivot)
|
|
return SustNeg
|
|
|
|
def ImagenMorfismo(L,XX,YY,S,LRv,dicv,inc):
|
|
i,j=L
|
|
res=XX[L].change_ring(S)
|
|
ai=tt([i],LRv).subs(dicv)
|
|
aj=tt([j],LRv).subs(dicv)
|
|
aij=(ai*aj).truncate(2)
|
|
bij=(ai-aij)
|
|
cij=(aj-aij)
|
|
res+=sum([(bij*YY[i,u,v]-cij*YY[j,u,v])*XX[u,v].change_ring(S) for (u,v) in inc])
|
|
return res
|
|
|
|
|
|
ordenPos=Permutation([1,3,7,5,8,11,4,10,9,6,2])
|
|
wiringPos=[[(), [10, 9]], [(), [5, 8]], [(), [5, 11, 4, 9]], [(), [5, 10]], [(),
|
|
[5, 6]], [(), [5, 2]], [(-7, -8), [7, 8]], [(), [7, 9]], [(), [7, 4]],
|
|
[(), [7, 10, 6]], [(), [7, 11, 2]], [(-8, -4, 7), [6, 11]], [(-7, -5,
|
|
-6, -4, 8), [3, 8, 11]], [(), [3, 4]], [(), [3, 10]], [(), [3, 9, 2,
|
|
6]], [(3,), [8, 10]], [(4, 5, 2, 3, 4, -2), [1, 8, 4, 6]], [(), [1, 11,
|
|
10]], [(), [1, 2]], [(), [1, 9]], [(-3, -4), [8, 2]]]
|
|
ordenNeg=Permutation([1,7,5,3,4,10,11,8,2,6,9])
|
|
wiringNeg=[[(), [3, 4]], [(), [3, 10]], [(), [3, 11, 8]], [(), [3, 2, 6, 9]],
|
|
[(-5, -6, -7, -4, -5), [5, 8]], [(), [5, 11, 4, 9]], [(), [5, 10]], [(),
|
|
[5, 6]], [(), [5, 2]], [(-4, 3, 6), [11, 6]], [(-6, -5), [9, 10]], [(4,
|
|
5, 4, 8, -7, 6), [2, 8]], [(7,), [7, 4]], [(), [7, 10, 6]], [(), [7,
|
|
8]], [(), [7, 9]], [(), [7, 2, 11]], [(-4, 5, -6, -3), [1, 4, 8, 6]],
|
|
[(), [1, 9]], [(), [1, 11, 10]], [(), [1, 2]], [(-2, -4), [8, 10]]]
|
|
n=11
|
|
B=BraidGroup(n)
|
|
F=FreeGroup(n)
|
|
|
|
|
|
GrupoListaPos=list_of_relations_2(ordenPos,wiringPos)
|
|
GrupoListaNeg=list_of_relations_2(ordenNeg,wiringNeg)
|
|
combPos=[sorted(v[0]) for v in GrupoListaPos]
|
|
combNeg=[sorted(v[0]) for v in GrupoListaNeg]
|
|
print "Do combinatorics coincide? ",sorted(combPos)==sorted(combNeg)
|
|
# Construct the list inc as a basis of commutators in G_1/G_2
|
|
comb=[]
|
|
for v in combPos:
|
|
for j in v[1:]:
|
|
comb.append([v[0],j])
|
|
tot=[tuple(sorted(_.list())) for _ in Subsets([1..n],2)]
|
|
inc=[_ for _ in tot if list(_) not in comb]
|
|
|
|
# The variables of the ring S are the unknowns of the final integral equation
|
|
xx=var(['v%da%db%d'% (k,i,j) for k in [1..n] for (i,j) in inc])
|
|
S=PolynomialRing(ZZ,xx)
|
|
|
|
# The dictionnary YY relates the index of the unknowns with the morphism of groups.
|
|
YY={}
|
|
for k in [1..n]:
|
|
for l in range(len(inc)):
|
|
YY[k,inc[l][0],inc[l][1]]=S.gen((k-1)*len(inc)+l)
|
|
|
|
LR=LaurentPolynomialRing(ZZ,'t',n)
|
|
LRv=LR.change_ring(S)
|
|
R=LR.polynomial_ring()
|
|
T=PowerSeriesRing(S,'s',num_gens=n,default_prec=2)
|
|
T0=T.change_ring(ZZ)
|
|
HomLRT0=R.hom([1+v for v in T0.gens()],codomain=T0,check=True)
|
|
dic={v:HomLRT0(v) for v in LR.gens()}
|
|
dicv={v:HomLRT0(v).change_ring(S) for v in LRv.gens()}
|
|
|
|
#We work with several modules, with basis the set of commutators. The elements XX[i,j] gives the commutator (any sign and order) with respect to the ring of Laurent polynomials
|
|
|
|
M=FreeModule(LR,n*(n-1)/2)
|
|
#MT=M.change_ring(T0)
|
|
#Mv=M.change_ring(T)
|
|
#XX={(i,j):M.gen(n*(i-1)-i*(i+1)/2+j-1) for i in range(1,n) for j in range(i+1,n+1)}
|
|
XX={tot[i]:M.gen(i) for i in range(n*(n-1)/2)}
|
|
for i in range(1,n+1):
|
|
XX[i,i]=M(0)
|
|
XX[-i,-i]=M(0)
|
|
XX[i,-i]=M(0)
|
|
XX[-i,i]=M(0)
|
|
for j in range(i+1,n+1):
|
|
XX[-i,j]=-tt([i],LR)^-1*XX[i,j]
|
|
XX[i,-j]=-tt([j],LR)^-1*XX[i,j]
|
|
XX[-i,-j]=tt([i],LR)^-1*tt([j],LR)^-1*XX[i,j]
|
|
XX[j,i]=-XX[i,j]
|
|
XX[-j,i]=-XX[i,-j]
|
|
XX[j,-i]=-XX[-i,j]
|
|
XX[-j,-i]=-XX[-i,-j]
|
|
|
|
# Translate the relations in the groups as relations for the Alexander invariants
|
|
relAlexPos=[]
|
|
for v in GrupoListaPos:
|
|
relAlexPos+=CommCyclic1(v,F,LR,XX,dir='LR')
|
|
print "Alexander invariant for first group"
|
|
relAlexNeg=[]
|
|
for v in GrupoListaNeg:
|
|
relAlexNeg+=CommCyclic1(v,F,LR,XX,dir='LR')
|
|
nrels=len(relAlexNeg)
|
|
print "Alexander invariant for the second group"
|
|
|
|
# The above relations are written in the power series ring truncated at level 2
|
|
relAlexSeriePos=Matrix([vector(w.subs(dic) for w in v.list()) for v in relAlexPos])
|
|
relAlexSerieNeg=Matrix([vector(w.subs(dic) for w in v.list()) for v in relAlexNeg])
|
|
|
|
#This matrix codifies each commutator in terms of the basis inc
|
|
SustNeg=EscalonarM2(relAlexSerieNeg,n)
|
|
print "The relations are used to write every one in terms of the basis inc"
|
|
|
|
# Image of each commutator of the first group in the second group
|
|
TotImagenMorfismo=[]
|
|
for u in tot:
|
|
v=ImagenMorfismo(u,XX,YY,S,LRv,dicv,inc)
|
|
TotImagenMorfismo.append(v)
|
|
if u[-1]==n:
|
|
print "Finished pairs with line ", u[0]
|
|
|
|
relAlexVarPos=[]
|
|
for ser in relAlexSeriePos:
|
|
vct=0
|
|
for j in range(n*(n-1)/2):
|
|
vct+=ser[j].change_ring(S)*TotImagenMorfismo[j]
|
|
relAlexVarPos.append(vct)
|
|
relAlexVarPos=MatTrunc(Matrix(relAlexVarPos))
|
|
relAlexVarPos=MatTrunc(relAlexVarPos*SustNeg.change_ring(T).transpose())
|
|
print "Images of relations of first group in terms of the basis inc in the second group, done"
|
|
|
|
relZPos=[]
|
|
for prueba in relAlexVarPos:
|
|
relZPos.append(vector(flatten([[pr1.derivative(v).constant_coefficient() for v in T.gens()] for pr1 in prueba])))
|
|
relZPos=Matrix(nrels,relZPos)
|
|
print "Integral matrix from relations"
|
|
|
|
|
|
#Adding Jacobi relations in the base inc and in the associated one in the next level
|
|
JCB=[]
|
|
for i in range(1,n-1):
|
|
for j in range(i+1,n):
|
|
for k in range(j+1,n+1):
|
|
JCB+=[T0.gen(i-1)*XX[j,k].change_ring(T0)+T0.gen(j-1)*XX[k,i].change_ring(T0)+T0.gen(k-1)*XX[i,j].change_ring(T0)]
|
|
JCB=Matrix(JCB)
|
|
JCB1=MatTrunc(JCB*SustNeg.transpose())
|
|
JCB2=Matrix(JCB.nrows(),flatten([[v.derivative(w).constant_coefficient() for w in T0.gens()] for v in JCB1.list()]))
|
|
print "Simplified Jacobi relations as integral matrix done"
|
|
|
|
#Eliminating generators from Jacobi relations (if no torsion)
|
|
SF,U,V=JCB2.smith_form()
|
|
Jdiag=[SF[v,v] for v in range(SF.rank())]
|
|
if Set(Jdiag)!=Set([1]):
|
|
print "Torsion at level 2"
|
|
print "Smith form of Jacobi relations, done", SF.ncols()-SF.rank()," generators left"
|
|
|
|
# Reduce the relations taking into account Jacobi relations (no torsion!)
|
|
eqs=(relZPos*V).matrix_from_columns([SF.rank()..JCB2.ncols()-1])
|
|
eqs1=[_ for _ in list(Set(eqs.list())) if _!=0]
|
|
print len(eqs1)," equations in ",len(inc)*n," unknowns."
|
|
|
|
# Put the system in matrix for, print the diagonal of the Smith form and a particular solution
|
|
Aeq=Matrix([vector(eq.monomial_coefficient(v) for v in S.gens()) for eq in eqs1])
|
|
Beq=vector(-eq.constant_coefficient() for eq in eqs1)
|
|
print "Ranks: ", Aeq.rank(),Aeq.augment(Beq).rank()
|
|
U1,U2,U3=Aeq.smith_form()
|
|
diageq=[U1[v,v] for v in range(U1.rank())]
|
|
diageq1=[_ for _ in diageq if _!=1]
|
|
print "Ones in the diagonal of the smith form: ",diageq.count(1)
|
|
print "Rest of the diagonal of the smith form: ",diageq1
|
|
print "Non integers in the Particular Solution:", [_ for _ in U1.solve_right(U2*Beq) if _ not in ZZ]
|
|
|
|
|
|
|
|
|
|
ordenPos1=copy(ordenPos)
|
|
wiringPos1=[[tuple(-i for i in _[0]),_[1]] for _ in wiringPos]
|
|
|
|
|
|
|
|
GrupoListaPos1=list_of_relations_2(ordenPos1,wiringPos1)
|
|
combPos1=[sorted(v[0]) for v in GrupoListaPos1]
|
|
print "Do combinatorics coincide? ",sorted(combPos1)==sorted(combNeg)
|
|
# Construct the list inc as a basis of commutators in G_1/G_2
|
|
|
|
# Translate the relations in the groups as relations for the Alexander invariants
|
|
relAlexPos1=[]
|
|
for v in GrupoListaPos1:
|
|
relAlexPos1+=CommCyclic1(v,F,LR,XX,dir='LR')
|
|
print "Alexander invariant for first group"
|
|
|
|
# The above relations are written in the power series ring truncated at level 2
|
|
relAlexSeriePos1=Matrix([vector(w.subs(dic) for w in v.list()) for v in relAlexPos1])
|
|
|
|
|
|
|
|
relAlexVarPos1=[]
|
|
for ser in relAlexSeriePos1:
|
|
vct=0
|
|
for j in range(n*(n-1)/2):
|
|
vct+=ser[j].change_ring(S)*TotImagenMorfismo[j]
|
|
relAlexVarPos1.append(vct)
|
|
relAlexVarPos1=MatTrunc(Matrix(relAlexVarPos1))
|
|
relAlexVarPos1=MatTrunc(relAlexVarPos1*SustNeg.change_ring(T).transpose())
|
|
print "Images of relations of first group in terms of the basis inc in the second group, done"
|
|
|
|
relZPos1=[]
|
|
for prueba in relAlexVarPos1:
|
|
relZPos1.append(vector(flatten([[pr1.derivative(v).constant_coefficient() for v in T.gens()] for pr1 in prueba])))
|
|
relZPos1=Matrix(nrels,relZPos1)
|
|
print "Integral matrix from relations"
|
|
|
|
|
|
# Reduce the relations taking into account Jacobi relations (no torsion!)
|
|
eqs_1=(relZPos1*V).matrix_from_columns([SF.rank()..JCB2.ncols()-1])
|
|
eqs1_1=[_ for _ in list(Set(eqs_1.list())) if _!=0]
|
|
print len(eqs1_1)," equations in ",len(inc)*n," unknowns."
|
|
|
|
# Put the system in matrix for, print the diagonal of the Smith form and a particular solution
|
|
Aeq1=Matrix([vector(eq.monomial_coefficient(v) for v in S.gens()) for eq in eqs1_1])
|
|
Beq1=vector(-eq.constant_coefficient() for eq in eqs1_1)
|
|
print "Ranks: ", Aeq1.rank(),Aeq1.augment(Beq1).rank()
|
|
U1_1,U2_1,U3_1=Aeq1.smith_form()
|
|
diageq_1=[U1_1[v,v] for v in range(U1_1.rank())]
|
|
diageq1_1=[_ for _ in diageq_1 if _!=1]
|
|
print "Ones in the diagonal of the smith form: ",diageq_1.count(1)
|
|
print "Rest of the diagonal of the smith form: ",diageq1_1
|
|
print "Non integers in the Particular Solution:", [_ for _ in U1_1.solve_right(U2_1*Beq1) if _ not in ZZ]
|