#Function showpaths #Just a function which plot the minimum spanning tree of the critical # points of F. showpaths:=proc(F,incx,incy) local crit,tree,pol,x,y,RF; crit:=table(); tree:=table(); pol:=table(); x,y:=incx,incy; RF:=sqrfree(resultant(F,diff(F,y),y))[2]; `if`(nargs=3,pointstree(RF,x,crit,pol),pointstree(RF,x,crit,pol,args[4])); findtree(crit,tree); # intermediarypoints(crit,tree); plotgraph(crit,tree); end; #Function onlypatha # Here we only compute the paths. This function is to test this part. onlypaths:=proc(F,x,y) local crit,tree,pol,t1,RF,sqrRF; t1:=time(); # we first define table used in our program crit:=table(); pol:=table(); tree:=table(); RF:=evala(resultant(numer(F),diff(numer(F),y),y)); sqrRF:=sqrfree(RF,x)[2]; `if`(nargs=3,pointstree(sqrRF,x,crit,pol),pointstree(sqrRF,x,crit,pol,args[4])); findtree(crit,tree); localorder(crit); findpath(crit,tree); crit,tree,time()-t1;; end; # Function monodromy # That's the general function. # Input: - F the function which defines the Riemann surface. # - x the first unknown. # - y the second unknown. # Output: - a the base point. # - ya the points of the Riemann surface over a. # - mon the monodromy group, which is presented as a list of couple b[i],permurtation group associated at the critical point. monodromy:=proc(f,incx,incy) local RF,F,x,y,t1,t0,i,numtot,con,monodro,alpha,k,T,a,basept,showtree,base,optio,opt,pol,isdebug,crit,d,poly,tree,sqrRF,z,K,M,SR,ext,j,prime,prov,S; t1:=time(); # we first define table used in our program crit:=table(); pol:=table(); tree:=table(); # now we look at options which are in the input. optio:=[args[4..nargs]]; opt:=map2(op,1,optio); if member('primenumber',opt,i) then prime:=op([i,2],optio) fi; if member('basepoint',opt,'i') then basept:=true; base:=op([i,2],optio); else basept:=false; fi; showtree:=member('displaygraph',opt); # if member('numstep',opt,'i') then # step:=true; # nstep:=op([i,2],optio); # else # step:=false; # fi; isdebug:=member('debugging',opt); # we fix F with local unknowns. F:=eval(f,{incx=x,incy=y,I=RootOf(x^2+1)}); d:=degree(F,y); # we now begin computations t0:=time(); # We want only one primitive element for the coefficient field. Thus, # we begin to create this primitive element if necessary. ext:=`algcurves/g_ext_r`(F); if nops(ext)>1 then K:=evala(Primifield(F)); F:=eval(F,K[2]); M:=eval(op([1,1,1,1],K),_Z=z); elif nops(ext)=1 then M:=eval(op([1,1],ext),_Z=z); F:=evala(F); else M:=z; fi; RF:=evala(resultant(numer(F),diff(numer(F),y),y)); sqrRF:=sqrfree(RF,x)[2]; if not(assigned(prime)) then SR:=evala(RF/gcd(RF,diff(RF,x))); S:=evala(resultant(SR,diff(SR,x),x)); prime:=LVGP(F,x,y,M,z,S); fi; userinfo(3,'monodromy',`Computing the points of the tree`); `if`(basept,pointstree(sqrRF,x,crit,pol,base),pointstree(sqrRF,x,crit,pol)); userinfo(3,'monodromy',`running time`,time()-t0); t0:=time(); userinfo(3,'monodromy',`Computing the tree`); findtree(crit,tree); userinfo(3,'monodromy',`running time`,time()-t0); t0:=time(); userinfo(3,'monodromy',`Computing singular parts of Puiseux expansions`); poly:=pol['list']; for i in poly do prov:=mypuiseux(F,x,y,i[1],0,'valuation'=i[2],'primenumber'=prime,T,'roots'=pol['roots'][i[1]],'moreterms' #,'irreducible' ); for j in prov do crit[pol[op([1,1,2,2],j)]['index']]['pui']:=j; #print(j,"coucou",seq(op([1,2,2],j),k in j)); crit[pol[op([1,1,2,2],j)]['index']]['ramif']:=[seq(degree(op([1,2],k),T),k in j)]; #print(pol[op([1,1,2,2],j)]['index']); od; od; # return([crit,pol,tree,[alpha,T,x,y]]); userinfo(3,'monodromy',`running time`,time()-t0); t0:=time(); userinfo(3,'monodromy',`Computing intermediary points`); numtot:=intermediarypoints(crit,tree); userinfo(3,'monodromy',`running time`,time()-t0); userinfo(2,'monodromy',`Total number of intermediary points`,numtot); if showtree then plotgraph2(crit,tree); fi; t0:=time(); userinfo(3,'monodromy',`Computing the precision needed for evaluations`); precision(F,x,y,d,tree,crit['nbcrit']); userinfo(3,'monodromy',`running time`,time()-t0); t0:=time(); userinfo(3,'monodromy',`Computing truncation orders`); truncationorder(F,x,y,d,crit,tree); userinfo(3,'monodromy',`running time`,time()-t0); t0:=time(); userinfo(3,'monodromy',`Computing Puiseux expansions`); setpuiseux(F,x,y,alpha,T,crit,pol,tree); userinfo(3,'monodromy',`running time`,time()-t0); t0:=time(); userinfo(3,'monodromy',`Computing local orders`); #return(crit); localorder(crit); userinfo(3,'monodromy',`running time`,time()-t0); t0:=time(); userinfo(3,'monodromy',`Computing the set of paths`); findpath(crit,tree); userinfo(3,'monodromy',`running time`,time()-t0); t0:=time(); #userinfo(3,'monodromy',`Computing the list of connection we have to do for each edge of the tree`); # segconnect(crit,tree); #userinfo(3,'monodromy',`running time`,time()-t0); # t0:=time(); userinfo(3,'monodromy',`Computing the connection of each vertex`); con:=link(crit,tree,alpha,x,d); userinfo(3,'monodromy',`running time`,time()-t0); t0:=time(); userinfo(3,'monodromy',`Computing the monodromy`); monodro:=mono(con,crit,tree,d,x,alpha); userinfo(3,'monodromy',`running time`,time()-t0); userinfo(1,'monodromy',`total time`,time()-t1); a:=crit[0]['val']; # res:=[a,eval(crit[0]['pui'],x=a),[seq([crit[i]['val'],convert(monodro[i],'disjcyc')],i=1..crit['nbcrit'])]] `if`(isdebug,[ [a,eval(crit[0]['pui'],x=a),[seq([crit[i]['val'],convert(monodro[i],'disjcyc')],i=1..crit['nbcrit'])]], crit,pol,tree,con,monodro,[alpha,T,x,y]],[a,eval(crit[0]['pui'],x=a),[seq([crit[i]['val'],convert(monodro[i],'disjcyc')],i=1..crit['nbcrit'])]]) # `if`(isdebug,[res,[crit,pol,tree]],res); end: # Function esqrt # Input: - z a complex number # - e the exponent # - alpha the argument of the branch cut # Output: - the e-th root of z according to the branch cut defined by alpha esqrt:=proc(z,e,alpha) local evaz; evaz:=evalf(z); if evaz::complex and alpha::realcons then if evaz=0 then return 0 fi; if argument(evaz)1,abs(b[1]-b[num]),abs(b[1]-b[2])); for i from 2 to nops(b) do dist:=`if`(i<>num and abs(b[i]-b[num]){} do value:=abs(seen[1]-notseen[1]): arg:=argument(seen[1]-notseen[1]): numseen:=1: numnotseen:=1: for i to nops(notseen) do for j to nops(seen) do better:=abs(seen[j]-notseen[i])segm[2] or abs(pt1-pt2)[Re(x),Im(x)],pts[i]),i=1..n)]; P:=plot(graph,'axes'='BOXED','title'="Expansion and evaluation points along the euclidean minimum spanning tree"); pts:=[seq(op(tree[i]['ev'][1]),i=1..n),seq(op(tree[i]['ev'][2]),i=1..n)]; graph:=[seq([Re(pts[i]),Im(pts[i])],i=1..nops(pts))]; P1:=plot(graph,'axes'='BOXED','style'='point','color'='red'); pts:=[seq(op(tree[i]['m'][1]),i=1..n),seq(op(tree[i]['m'][2]),i=1..n),seq(tree[i]['mid'],i=1..n),seq(crit[i]['val'],i=1..n)]; graph:=[seq([Re(pts[i]),Im(pts[i])],i=1..nops(pts))]; P2:=plot(graph,'axes'='BOXED','style'='point','color'='blue'); print(plots['display'](P,P1,P2)); end: plotgraph:=proc(crit,tree) #It creates the graph of the tree of critical points. local n,pts,graph,i; n:=crit['nbcrit']; pts:=seq([crit[tree[i]['seg'][1]]['val'],crit[tree[i]['seg'][2]]['val']],i=1..n); graph:=[seq(map(x->[Re(x),Im(x)],pts[i]),i=1..n)]; plot(graph,'axes'='BOXED'); end: # Function precision # It computes the set of precision needed in order to have reliable connections. prec:=proc(F,x,y,d,x0,tree) local provDig,inter,yy,rho,l,h,k; provDig:=Digits; inter:=true; while inter do yy:=fsolve(subs(x=x0,F)=0,y,complex); rho:=[seq(evalf(d*abs(subs({x=x0,y=yy[l]},F)/(mul(yy[l]-yy[k],k=1..l-1)*mul(yy[l]-yy[k],k=l+1..d)))),l=1..d)]; # rho is the list of the Smith's radius. We now look if the circle have an intersection for l to d-1 do for h from l+1 to d do inter:=`if`(rho[l]+rho[h] dist=abs(x0-x1) # -> delta=abs(x0-b) for k to 2 do for i to crit['nbcrit'] do segm:=tree[i]['seg']; mm:=tree[i]['m'][k]; p:=nops(mm); z:=abs(crit[segm[k]]['val']-crit[segm[k]]['nearcrit']); for j to p do dist:=`if`(j=1,z/2,z*2^(j-3)); delta:=z*2^(j-1); r:=radius(delta,dist); M:=maxcircle(poly,mm[j],x,d,r); tree[i]['n'][k][j]:=truncation(tree[i]['epsilon'][k][j],M,r,dist); dist:=`if`(j=p,abs(tree[i]['mid']-mm[p])/2,z*2^(j-2)); r:=radius(delta,dist); M:=maxcircle(poly,mm[j],x,d,r); tree[i]['n'][k][j]:=max(truncation(tree[i]['epsilon'][k][j+1],M,r,dist),tree[i]['n'][k][j]); od; # we look the midpoint m[i] delta:=abs(tree[i]['mid']-crit[segm[k]]['val']); dist:=`if`(p=0,delta/2,dist); r:=radius(delta,dist); M:=maxcircle(poly,tree[i]['mid'],x,d,r); prov:=truncation(tree[i]['epsilon'][k][p+1],M,r,dist); tree[i]['n']['m']:=`if`(k=1,prov,max(prov,tree[i]['n']['m'])); # we look the critical point pts[segm[k]] delta:=abs(crit[segm[k]]['val']-crit[segm[k]]['nearcrit']); dist:=`if`(p>=1,z/2,dist); #print(crit[segm[k]]['ramif']); for j in {`if`(segm[k]=0,1,op(crit[segm[k]]['ramif']))} do prov:=truncrit(tree[i]['epsilon'][k][1],j,crit[segm[k]]['val'],delta,dist,d,x,poly); crit[segm[k]]['n']:=`if`(type(crit[segm[k]]['n'],realcons),max(crit[segm[k]]['n'],prov),prov); od; od; od; end: # Function setpuiseux # It computes the set of the puiseux expansions needed to compute the monodromy. # à retravailler en utilisant des développements # symboliques/numériques pour les points ramifiés. myeval:=proc(pui,T,x,alpha) # it values a Puiseux expansion expressed with T in x, computing all # the conjugates. # input: a puiseux expansion in the form [x=a*T^e+b,y=g(T)] # output: g(1/a*(x-b)^(1/e)) e times (one for each root of x^e-1). local prov,e,oneroot,k; prov:=convert(op([2,2],pui),'horner',T); e:=degree(op([1,2],pui),T); oneroot:=evalf([seq(RootOf(_Z^e-1,index=k),k=1..e)]); # je mets ca plutot qu'un fsolve pour etre sur de l'ordre. seq(eval(prov,T=oneroot[k]*esqrt((x-coeff(op([1,2],pui),T,0))/coeff(op([1,2],pui),T,e),e,alpha)),k=1..e); end: setpuiseux:=proc(F,x,y,alpha,T,crit,pol,tree) local i,t0,puis,tab,j,l,k,p,poly,m1,m2,d,S,G,N,co,ind,pu; poly:=pol['list']; for i in poly do t0:=time(): for j in pol[i[1]]['index'] do pu:=crit[j]['pui']; puis:=NULL; for k in pu do d:=degree(op([2,2],k),T); G:=evalf(expand(eval(F,{x=eval(op([1,2],k),T=x),y=eval(op([2,2],k),T=x)+x^d*y}))); co:=[coeffs(G,{x,y},'ind')]; ind:=[ind]; G:=add(`if`(degree(ind[l],x)=arg(b-a) if argument(b-a) <=0 then evalb(argument(alpha-a)>argument(b-a) and argument(alpha-a)<= evalf(Pi)+argument(b-a)) else not(evalb(argument(alpha-a)<=argument(b-a) and argument(alpha-a)> evalf(-Pi)+argument(b-a))) fi; end; inter:=proc(tree,crit,l) # It gives the edges of the tree which intersect the segment # [a,alpha_l]. local L,i,a,b,f,t,T1,T2,A,B; f:=proc() (Im(crit[b]['val'])-Im(crit[a]['val']))*T1+(Re(crit[a]['val'])-Re(crit[b]['val']))*T2=Re(crit[a]['val'])*Im(crit[b]['val'])-Im(crit[a]['val'])*Re(crit[b]['val']) end; T1:=t*Re(crit[l]['val']-crit[0]['val'])+Re(crit[0]['val']); T2:=t*Im(crit[l]['val']-crit[0]['val'])+Im(crit[0]['val']); L:=NULL; A:=crit[0]['val']; B:=crit[l]['val']; for i to crit['nbcrit'] do a,b:=op(tree[i]['seg']); if not member(0,[a,b]) then if Re(B)>=Re(A) then if min(a,b) < l and l < max(a,b) and max(Re(crit[a]['val']),Re(crit[b]['val']))>max(Re(A)) then L:=L,[i,fsolve(f(),t)]; fi; elif Im(B) l and max(Re(crit[a]['val']),Re(crit[b]['val'])) Im(A) and Im(A) > Im(crit[min(a,b)]['val'])) then L:=L,[i,fsolve(f(),t)]; fi; else if (min(a,b) < l and l < max(a,b) and Im(crit[min(a,b)]['val']) > Im(A)) or (max(a,b) < l and max(Re(crit[a]['val']),Re(crit[b]['val'])) Im(A) and Im(A) > Im(crit[min(a,b)]['val'])) then L:=L,[i,fsolve(f(),t)]; fi; fi; fi; od; # L contient les intersections avec la demi droite [a,alpha_l) L:=sort([L,['pt',1]],proc(i,j) evalb(i[2] 0 and `if`(i=0,true,not(member(searched,tree[`if`(j='pt',i,min(i,j))]['seg']))) do k:=crit[searched]['found']; path:=k,path; searched:=tree[k]['seg'][1]; od; if searched=0 and i<>0 then searched:=tree[`if`(j='pt',i,min(i,j))]['seg'][1]; path2:=NULL; while searched <> 0 do k:=crit[searched]['found']; path2:=path2,k; searched:=tree[k]['seg'][1]; od; path:=path2,path; fi; [path]; end; sens:=proc(tau,L) local eps,i; eps:=-1; for i in tau do if member(i,L) then eps:=-eps; fi; od; eps; end; followtree:=proc(crit,tree,i1,i2,h,l,eps) local j,L,Lg,path,b,k,w,sigma,n,i,ww,a1,a2,a3; if h=0 then j:=0; L:=crit[0]['close']; if eps=1 then Lg:=seq(`if`(i>l,i,NULL),i in L); k:=`if`(Lg=NULL,min(op(L)),min(Lg)); else Lg:=seq(`if`(ia3 or a2a3,a1>a2 and a2>a3,a2a3)) then b:=false; path:=path,[k,w] else path:=path,[k,w]; j,k:=k,w; fi; elif (tree[[k,w]]['index']=i2 and ((eps=-1 and tauplane(crit[w]['val'],crit[0]['val'],crit[l]['val'])) or (eps=1 and tauplane(crit[k]['val'],crit[0]['val'],crit[l]['val'])))) then b:=false; else path:=path,[k,w]; j,k:=k,w; fi; od; path; end; findpath:=proc(crit,tree) local n,l,pathi,L,h,lastpt,pathh,eps,tau; n:=crit['nbcrit']; for l to n do if member(l,crit[0]['close']) then crit[l]['path']:=[tree[crit[l]['found']]['seg']]; else # path:=NULL; inter(tree,crit,l); L:=crit[l]['inter']; tau:=connect(crit,tree,0,L[1],l); eps:=sens(tau,[op(L[2..-1]),op(crit[l]['moreinter'])]); lastpt:=`if`(member(l,tree[tau[-1]]['seg']),tree[tau[-1]]['seg'][1],tree[tau[-1]]['seg'][2]); if tauplane(crit[lastpt]['val'],crit[0]['val'],crit[l]['val']) then eps:=-eps; fi; if member(l,[seq(op(tree[i]['seg']),i in tau[1..-2])]) then eps:=-eps fi; pathi:=followtree(crit,tree,0,L[1],0,l,eps); for h to nops(L)-1 do tau:=connect(crit,tree,L[h],L[h+1],l); eps:=sens(tau,[op(L[h+2..-1]),op(crit[l]['moreinter'])]); lastpt:=`if`(tau=[],op({op(tree[L[h]]['seg'])} intersect {op(tree[L[h+1]]['seg'])}),`if`(L[h+1]='pt',tree[tau[-1]]['seg'][1],`if`(L[h] [] and member(l,[seq(op(tree[i]['seg']),i in tau[1..-2])]) then eps:=-eps fi; pathh:=followtree(crit,tree,L[h],L[h+1],h,l,eps); if [pathi][-1][2]=[pathh][1][1] then pathi:=pathi,pathh else pathi:=pathi,[[pathh][1][1],[pathi][-1][2]],pathh fi; od; crit[l]['path']:=[pathi]; fi; od; end; # Function link. # It computes the links between the solutions of F(x,y) over b[tree[i,1]] and those over b[tree[i,2]] for each i. numbranch:=proc(valj,eps,valy2,d,z) # it computes the y-value of valy2 corresponding to the y-value valj # with precision eps. local res,k; for k to d do if abs(valj-valy2[k])theta2 and sens=-1) then if theta>0 then theta:=theta-Pi; else theta:=theta+Pi fi; fi; # theta is the argument of the branch cut we want to use. # in order to get this branch cut, we have to look at the coefficient a # in x in the function esqrt and to evaluate this function in # theta+argument(a). # Correction : with the numerical newton puiseux algorithm, a is equal # to 1. Thus, we do not need to consider this here. if tree[numfrom]['seg'][1]=i then # nfrom:=tree[numfrom]['seg'][2]; cote1:=1; else # nfrom:=tree[numfrom]['seg'][1]; cote1:=2; fi; if tree[numto]['seg'][1]=i then # nto:=tree[numto]['seg'][2]; cote2:=1; else # nto:=tree[numto]['seg'][1]; cote2:=2; fi; # Digits:=crit[i]['dig']; eva1:=tree[numfrom]['ev'][cote1][1]; valy1:=eval(crit[i]['pui'],{x=eva1,alpha=theta}); eva2:=tree[numto]['ev'][cote2][1]; valy2:=eval(crit[i]['pui'],{x=eva2,alpha=theta}); prov1:=table([seq(numbranch(tree[eva1]['fiber'][l],tree[numfrom]['epsilon'][cote1][1],valy1,d,z),l=1..d)]); if member(z,[seq(prov1[l],l=1..d)]) then error "increase Digits" fi; link[j]:=table([seq(numbranch(valy2[prov1[l]],tree[numto]['epsilon'][cote2][1],tree[eva2]['fiber'],d,z),l=1..d)]); if member(z,[seq(link[j][l],l=1..d)]) then error "increase Digits" fi; Digits:=Dig; od; od; link; end: # Function mono # It is the final function. It connects the segments of the path one by one mono:=proc(link,crit,tree,d,x,alpha) local i,pathi,n,eva,valy1,valy2,prov,z,provback,monodro,j,con,conback,cote,loop,l; for i to crit['nbcrit'] do pathi:=crit[i]['path']; n:=tree[pathi[1]]['index']; eva:=tree[n]['ev'][1][1]; valy1:=eval(crit[0]['pui'],x=eva); valy2:=tree[eva]['fiber']; prov:=table([seq(numbranch(valy2[l],tree[n]['epsilon'][1][1],valy1,d,z),l=1..d)]); if member(z,[seq(prov[l],l=1..d)]) then error "increase Digits" fi; # we first connect the base point to the first fiber. for j in pathi do prov:=table([seq(link[j][prov[l]],l=1..d)]); od; # prov contains connections for the path from the base point to the # last evaluation point close to alpha_i. provback:=table([seq(op([1,2,l,2],prov)=op([1,2,l,1],prov),l=1..d)]); n:=tree[pathi[-1]]['index']; cote:=`if`(tree[n]['seg'][1]=i,1,2); eva:=tree[n]['ev'][cote][1]; valy1:=eval(crit[i]['pui'],{x=eva,alpha=-Pi}); valy2:=tree[eva]['fiber']; con:=table([seq(numbranch(valy2[l],tree[n]['epsilon'][cote][1],valy1,d,z),l=1..d)]); if member(z,[seq(con[l],l=1..d)]) then error "increase Digits" fi; conback:=table([seq(op([1,2,l,2],con)=op([1,2,l,1],con),l=1..d)]); loop:=[seq(conback[crit[i]['perm'][con[l]]],l=1..d)]; monodro[i]:=[seq(provback[loop[prov[l]]],l=1..d)]; od; monodro; end: