diff --git a/CodeLines.sws b/CodeLines.sws new file mode 100644 index 0000000..2522c23 Binary files /dev/null and b/CodeLines.sws differ diff --git a/CodeLines.txt b/CodeLines.txt new file mode 100644 index 0000000..bd5628e --- /dev/null +++ b/CodeLines.txt @@ -0,0 +1,325 @@ +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]