Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
Project: admcycles
Views: 745Visibility: Unlisted (only visible to those who know the link)
Image: ubuntu2004r"""1Double ramification cycle2"""34from __future__ import absolute_import, print_function5from six.moves import range6from admcycles.admcycles import psiclass, list_strata, fundclass, lambdaclass7from admcycles.stable_graph import StableGraph89import itertools10from copy import deepcopy, copy1112from sage.combinat.integer_vector import IntegerVectors13from sage.arith.all import factorial14from sage.rings.all import QQ15from sage.rings.power_series_ring import PowerSeriesRing1617# S.<x0,x1>=PowerSeriesRing(QQ,'x0,x1',default_prec=14)18def graph_sum(g,n,decgraphs=None,globalfact=None, vertterm=None,legterm=None,edgeterm=None,maxdeg=None,deg=None,termsout=False):19r"""Returns the (possibly mixed-degree) tautological class obtained by summing over graphs gamma,20inserting vertex-, leg- and edgeterms.2122INPUT:2324- ``decgraphs`` -- list or generator; entries of decgraphs are pairs (gamma,dec) of a StableGraph25gamma and some additional combinatorial structure dec associated to gamma2627- ``globalfact`` -- function; globalfact(gamma,dec) gets handed the parameters gamma,dec as arguments and gives out a number that is multiplied with the corresponding term in the graph sum; default is 12829- ``vertterm`` -- function; vertterm(gv,nv,maxdeg **kwargs) takes arguments local genus gv and number of legs nv30and maxdeg gets handed the parameters gamma,dec,v as optional keyworded arguments and gives out a31tautological class on Mbar_{gv,nv}; the class is assumed to be of degree at most maxdeg,32if deg is given, the class is exactly of degree deg3334- ``legterm`` -- function; legterm(gv,nv,i,maxdeg, **kwargs) similar to vertterm, except input is35gv,nv,i,maxdeg where i is number of marking on Mbar_{gv,nv} associated to leg36gamma, dec given as keyworded arguments3738- ``edgeterm`` -- function; edgeterm(maxdeg,**kwargs) takes keyworded arguments gamma,dec,e,maxdeg39it gives a generating series s in x0,x1 such that the insertion at edge40e=(h0,h1) is given by s(psi_h0, psi_h1)4142- ``termsout`` -- parameter; if termsout=False, return sum of all terms43if termsout = 'coarse', return tuple of terms, one for each pair (gamma,dec)44if termsout = 'fine', return tuple of terms, one for each pair (gamma,dec) and each distribution45of cohomological degrees to vertices and half-edges46"""47if maxdeg is None:48if deg is None:49maxdeg = 3*g-3+n50else:51maxdeg = deg52if decgraphs is None:53decgraphs = [(gr,None) for ednum in range(3*g-3+n+1) for gr in list_strata(g,n,ednum)]54if globalfact is None:55globalfact = lambda a,b : 156if vertterm is None:57def vertterm(gv,nv,maxdeg, **kwargs):58return fundclass(gv,nv)59if legterm is None:60def legterm(gv,nv,i,maxdeg, **kwargs):61return fundclass(gv,nv)62if edgeterm is None:63def edgeterm(maxdeg,**kwargs):64S=PowerSeriesRing(QQ,'x0,x1',default_prec=maxdeg+1)65return S.one()666768termlist = []6970for (gamma,dec) in decgraphs:71restdeg = maxdeg - len(gamma.edges)72if restdeg < 0:73continue7475gammadectermlist=[]7677numvert = gamma.numvert()78gnvect=[(gamma.genera[i],len(gamma.legs[i])) for i in range(numvert)]79dimvect=[3*g-3+n for (g,n) in gnvect]80markings = gamma.list_markings()81vertdic = {l:v for v in range(numvert) for l in gamma.legs[v]}82indexdic = {l:j+1 for v in range(numvert) for j,l in enumerate(gamma.legs[v])}83# ex_dimvect=[dimvect[vertdic[l]] for l in halfedges] # list of dimensions of spaces adjacent to half-edges8485# Pre-compute all vertex-, leg- and edgeterms86vterms = {v:vertterm(gnvect[v][0],gnvect[v][1],restdeg, gamma=gamma,dec=dec,v=v) for v in range(numvert)}87lterms = {i:legterm(gnvect[vertdic[i]][0],gnvect[vertdic[i]][1],indexdic[i], restdeg, gamma=gamma,dec=dec) for i in markings}88eterms = {e: edgeterm(restdeg,gamma=gamma,dec=dec,e=e) for e in gamma.edges}89varlist = {(h0,h1): eterms[h0,h1].parent().gens() for h0,h1 in gamma.edges}90eterms = {e:eterms[e].coefficients() for e in eterms}91varx = {h0 : varlist[h0,h1][0] for h0,h1 in gamma.edges}92varx.update({h1 : varlist[h0,h1][1] for h0,h1 in gamma.edges})9394if deg is None:95rdlis = range(restdeg+1) # terms of all degrees up to restdeg must be computed96else:97rdlis = [deg - len(gamma.edges)]98for rdeg in rdlis:99# distribute the remaining degree rdeg to vertices100for degdist in IntegerVectors(rdeg,numvert,outer=dimvect):101# now for each vertex, split degree to vertex- and leg/half-edge terms102vertchoices = [IntegerVectors(degdist[v],len(gamma.legs[v])+1) for v in range(numvert)]103for choice in itertools.product(*vertchoices):104vdims = []105ldims = {}106for v in range(numvert):107vdims.append(choice[v][0])108ldims.update({l:choice[v][i+1] for i,l in enumerate(gamma.legs[v])})109110effvterms = [vterms[v].degree_part(vdims[v]) for v in vterms]111efflterms = {i: lterms[i].degree_part(ldims[i]) for i in lterms}112for i in efflterms:113effvterms[vertdic[i]]*=efflterms[i] # multiply contributions from legs to vertexterms114for h0,h1 in gamma.edges:115# TODO: optimization potential here by multiplying kppolys directly116effvterms[vertdic[h0]]*= eterms[(h0,h1)].get(varx[h0]**ldims[h0] * varx[h1]**ldims[h1],0)* (psiclass(indexdic[h0],*gnvect[vertdic[h0]]))**ldims[h0]117effvterms[vertdic[h1]]*= (psiclass(indexdic[h1],*gnvect[vertdic[h1]]))**ldims[h1]118for t in effvterms:119t.simplify()120#print(gamma)121#print(rdeg)122#print(degdist)123#print(choice)124#print(effvterms)125#print(eterms)126#print(indexdic)127#print('\n')128tempres=gamma.boundary_pushforward(effvterms)129tempres.simplify()130if(len(tempres.terms))>0:131tempres*=globalfact(gamma,dec)132gammadectermlist.append(tempres)133#print(termlist)134if termsout=='coarse':135termlist.append(sum(gammadectermlist))136else:137termlist+=gammadectermlist138if termsout:139return termlist140else:141return sum(termlist)142143############144#145# Useful functions and examples146#147############148149###150# Example 1 : Conjectural graph sum for DR_g(1,-1)151###152153# Generating functions for graphs154155def DR11_tree_test(gr):156return gr.vertex(1) == gr.vertex(2)157158159def DR11_trees(g, maxdeg=None):160if maxdeg is None:161maxdeg = 3*g-3+n # n is not defined !162return [gr for n in range(1,g+1) for e in range(min(n,maxdeg-n+1))163for gr in list_strata(0,2+n,e) if DR11_tree_test(gr)]164165166def DR11_graphs(g, maxdeg=None):167if maxdeg is None:168maxdeg = 3*g-3+2169result=[]170for gr in DR11_trees(g,maxdeg):171n=len(gr.list_markings())-2172maxleg=max([max(j+[0]) for j in gr.legs])173grlist=[]174for gdist in IntegerVectors(g,n,min_part=1):175genera=copy(gr.genera)+list(gdist)176legs=copy(gr.legs)+[[j] for j in range(maxleg+1,maxleg+n+1)]177edges=copy(gr.edges)+[(j-maxleg+2,j) for j in range(maxleg+1,maxleg+n+1)]178grlist.append(StableGraph(genera,legs,edges))179result+=[(gam,None) for gam in grlist]180removedups(result,lambda a,b : a[0].is_isomorphic(b[0]))181return result182183def removedups(li, comp=None, inplace=True):184if inplace:185l=li186else:187l=deepcopy(li) # could be done more efficiently188if comp is None:189comp = lambda a,b : a == b190n = len(l)191currn = len(l)192for i in range(n,-1,-1):193if any(comp(l[i],l[j]) for j in range(i+1,currn)):194l.pop(i)195currn-=1196return l197198# Global factor = 1/|Aut(Gamma)|199200def divbyaut(gamma,dec):201return QQ(1)/gamma.automorphism_number()202203# Vertex- and edgeterms for DR11204def DR11_vterm(gv, nv, maxdeg,**kwargs):205if gv==0:206gamma = kwargs['gamma']207v = kwargs['v']208if not 1 in gamma.legs[v]:209# we are in genus zero vertex not equal to base210return -nv * fundclass(gv,nv)211else:212# we are at the base vertex213return fundclass(gv,nv)214else:215return sum([(-1)**j * lambdaclass(j,gv,nv) for j in range(maxdeg+1)])216def DR11_eterm(maxdeg,**kwargs): # smarter: edterm(maxdeg=None,gamma=None,dec=None,e=None, *args, *kwds)217S=PowerSeriesRing(QQ,'x0,x1',default_prec=maxdeg+1)218x0,x1 = S.gens()219return 1/(1-x0-x1+x0*x1)220221# Final conjectural graph sum expressing DR_g(1,-1)222def DR11_sum(g,deg=None,**kwds):223if deg is None:224deg = g225return graph_sum(g,2,decgraphs=DR11_graphs(g,maxdeg=deg),globalfact=divbyaut,vertterm=DR11_vterm,edgeterm=DR11_eterm,deg=deg,**kwds)226227# decorate the graphs of DR11_graphs(g) with a choice of half-edge at each non-root vertex228def DR11_decgraphs(g,maxdeg=None):229if maxdeg is None:230maxdeg=3*g-3+2231graphs = DR11_graphs(g,maxdeg)232result = []233for gr in graphs:234L = [v for v in gr[0].legs if not (1 in v)]235for choice in itertools.product(*L):236result.append((gr[0],choice))237return result238239def divbyaut_new(gamma,dec):240zeroverts=gamma.genera.count(0)241return factorial(zeroverts-1)/gamma.automorphism_number()242243# Vertex- and edgeterms for DR11244def DR11_vterm_new(gv, nv, maxdeg,**kwargs):245if gv==0:246gamma = kwargs['gamma']247v = kwargs['v']248if not 1 in gamma.legs[v]:249# we are in genus zero vertex not equal to base250return -1 * fundclass(gv,nv)251else:252# we are at the base vertex253return fundclass(gv,nv)254else:255return sum([(-1)**j * lambdaclass(j,gv,nv) for j in range(maxdeg+1)])256257def DR11_eterm_new(maxdeg,**kwargs): # smarter: edterm(maxdeg=None,gamma=None,dec=None,e=None, *args, *kwds)258S=PowerSeriesRing(QQ,'x0,x1',default_prec=maxdeg+1)259x0,x1 = S.gens()260e = kwargs['e']261dec = kwargs['dec']262ex = 0263for i in e:264if i in dec:265ex += 1266return 1/((1-x0-x1)**ex)267268# Final conjectural graph sum expressing DR_g(1,-1)269def DR11_sum_new(g,deg=None,**kwds):270if deg is None:271deg = g272return graph_sum(g,2,decgraphs=DR11_decgraphs(g,maxdeg=deg),globalfact=divbyaut_new,vertterm=DR11_vterm_new,edgeterm=DR11_eterm_new,deg=deg,**kwds)273274275