Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
181 views
unlisted
ubuntu2004
1
from sage.rings.rational_field import QQ
2
from sage.matrix.constructor import matrix, vector
3
from sage.matrix.special import block_matrix
4
5
import admcycles.admcycles
6
from .admcycles import list_strata, generating_indices, pullback_matrix
7
8
9
def identify_class(tautring, d, pairfunction=None, pullfunction=None,
10
kappapsifunction=None, check=False):
11
r"""
12
Identify a tautological class in degree d by specifying its
13
intersection pairing with classes in complementary degree
14
and/or its pullback under boundary gluing morphisms.
15
16
INPUT::
17
18
- tautring (TautologicalRing) : ring containing the class that
19
is to be identified
20
21
- d (integer): degree of the class
22
23
- pairfunction (function, optional): function taking classes in
24
complementary degree and returning the intersection product with
25
the desired class
26
27
- pullfunction (function, optional): function taking stable graphs
28
with at most two vertices and returning the prodtautclass obtained
29
by pulling back the desired class under the associated boundary
30
gluing map
31
32
- kappapsifunction (function, optional): function taking as arguments
33
a list, dictionary and TautologicalClass (giving a polynomial in
34
kappa and psi-classes) and returning the intersection product of
35
the desired class with this polynomial (or None)
36
37
- check (bool, default = False) : whether to use FZ relations to
38
verify that intersection numbers/pullbacks are consistent with
39
known tautological relations
40
41
EXAMPLES::
42
43
sage: from admcycles.identify_classes import identify_class
44
sage: from admcycles import TautologicalRing
45
sage: R = TautologicalRing(2, 1)
46
sage: cl = 3 * R.psi(1) -2 * R.kappa(1)
47
sage: def pairf(a):
48
....: return (a * cl).evaluate()
49
sage: cl2 = R.identify_class(1, pairfunction = pairf)
50
sage: cl == cl2
51
True
52
sage: def pullf(gamma):
53
....: return gamma.boundary_pullback(cl)
54
....:
55
sage: cl3 = R.identify_class(1, pullfunction=pullf)
56
sage: cl == cl3
57
True
58
59
Here is some code to reconstruct the class 42*psi_1 on Mbar_0,6 from its intersection
60
numbers with psi-monomials (which have an explicit formula). Note that the associated
61
function kpfun is allowed to return None if kappa-classes show up::
62
63
sage: R = TautologicalRing(0,6)
64
sage: def kpfun(kap, psi, cl):
65
....: if kap:
66
....: return None
67
....: b = vector(ZZ,[psi.get(i,0) for i in range(1,7)])+vector([1,0,0,0,0,0])
68
....: return 42*factorial(3)/prod(factorial(bi) for bi in b)
69
....:
70
sage: cl4 = R.identify_class(1, kappapsifunction=kpfun)
71
sage: cl4 == 42*R.psi(1)
72
True
73
74
TESTS::
75
76
sage: R = TautologicalRing(2, 1)
77
sage: def bad_pairf(a):
78
....: return (a * cl).evaluate() if not (a - R.kappa(3)).is_empty() else 0
79
sage: R.identify_class(1, pairfunction = bad_pairf, check=True)
80
Traceback (most recent call last):
81
...
82
ValueError: intersection numbers or pullbacks are not consistent with FZ relations
83
"""
84
gens = tautring.basis(d)
85
ngens = len(gens)
86
d_dual = tautring.socle_degree() - d
87
M = matrix(QQ, 0, ngens)
88
v = []
89
rank_sufficient = (ngens == 0)
90
if pairfunction is not None and not rank_sufficient:
91
if check:
92
gens_dual = tautring.generators(d_dual)
93
else:
94
gens_dual = tautring.basis(d_dual)
95
ind_dcomp = tuple(generating_indices(tautring._g, tautring._n, d))
96
inters = tautring.pairing_matrix(d_dual, basis=not check, ind_dcomp=ind_dcomp)
97
M = block_matrix([[M], [inters]], subdivide=False)
98
v += [pairfunction(a) for a in gens_dual]
99
rank_sufficient = (M.rank() == ngens)
100
101
if pullfunction is not None and not rank_sufficient:
102
moduli = tautring._moduli
103
graphs = [gam for gam in list_strata(tautring._g, tautring._n, 1)
104
if not gam.vanishes(moduli)]
105
if len(graphs) > 0 and graphs[0].num_verts() == 1:
106
irrgraph = graphs.pop(0)
107
graphs.append(irrgraph)
108
for gam in graphs:
109
pulls = pullback_matrix(tautring._g, tautring._n, d, bdry=gam)
110
# pulls = [gam.boundary_pullback(a).totensorTautbasis(d, vecout=True)
111
# for a in gens]
112
M = block_matrix([[M], [pulls]],
113
subdivide=False)
114
v += list(pullfunction(gam).totensorTautbasis(d, vecout=True))
115
rank_sufficient = (M.rank() == ngens)
116
if rank_sufficient and not check:
117
break
118
119
if kappapsifunction is not None and not rank_sufficient:
120
for kappa, psi, cl in tautring.kappa_psi_polynomials(d_dual, True):
121
intnum = kappapsifunction(kappa, psi, cl)
122
if intnum is not None:
123
M = block_matrix(QQ, [[M], [matrix([[(c * cl).evaluate() for c in gens]])]], subdivide=False)
124
v.append(intnum)
125
rank_sufficient = (M.rank() == ngens)
126
if rank_sufficient and not check:
127
break
128
129
if not rank_sufficient:
130
raise ValueError('Intersection numbers and/or pullbacks are ' +
131
'not enough to determine this class')
132
try:
133
w = M.solve_right(vector(QQ, v))
134
except ValueError:
135
raise ValueError('intersection numbers or pullbacks are not consistent with FZ relations')
136
return tautring.from_basis_vector(w, d)
137
138
139
def Pullback_Matrices(g, n, d, ind_list=None):
140
r"""
141
Compute the pullback matrices of given degree d and list of
142
boundary stratum.
143
144
INPUT::
145
146
147
- ind_list (list): the list of indices of the boundary stratum,
148
0 indicates the first nontrivial graph
149
appearing in the generator
150
list of degree d tautological classes
151
152
EXAMPLES::
153
154
sage: from admcycles.identify_classes import Pullback_Matrices
155
sage: from admcycles import TautologicalRing
156
sage: Pullback_Matrices(1, 2, 1)
157
[
158
[1] [1]
159
[0], [1]
160
]
161
162
"""
163
L1 = admcycles.admcycles.tautgens(g, n, d)
164
Listgen1 = admcycles.admcycles.generating_indices(g, n, d)
165
L2 = admcycles.admcycles.tautgens(g, n, 1)
166
167
M_list = []
168
if not ind_list:
169
ind_list = range(len(L2) - n - 1)
170
171
for a in ind_list:
172
b = a + n + 1
173
M0 = []
174
Q = None
175
if b == len(L2) - 1:
176
Q = list(L2[b].standard_markings()._terms)[0]
177
else:
178
Q = list(L2[b]._terms)[0]
179
180
for i in Listgen1:
181
T = Q.boundary_pullback(L1[i])
182
M0 += [T.totensorTautbasis(d, vecout=True)]
183
M = matrix(M0)
184
M_list += [M]
185
return M_list
186
187
188
def solve_perfect_pairing(g, n, d, list_evaluate):
189
r"""
190
Identify a tautological class in degree d by specifying
191
its intersection pairing
192
with classes in complementary degree.
193
194
INPUT::
195
196
197
- list_evaluate (list) : the list of intersection numbers
198
199
- list_dual_classes (list): a list of classes of dual codimension
200
one wants to compute the intersection
201
(the program will complete the list
202
such that one obtain a full rank matrix)
203
204
205
EXAMPLES::
206
207
sage: from admcycles.identify_classes import solve_perfect_pairing
208
sage: from admcycles import TautologicalRing
209
sage: R = TautologicalRing(1,3)
210
sage: cl = R.psi(1) -2 * R.kappa(1)
211
sage: def pairf(a):
212
....: return (a * cl).evaluate()
213
sage: cl2 = solve_perfect_pairing(1, 3, 1,
214
....: [pairf(x) for x in R.generators(2)])
215
sage: cl == cl2
216
True
217
218
"""
219
d_dual = 3 * g - 3 + n - d
220
ind = admcycles.admcycles.generating_indices(g, n, d)
221
gen = admcycles.admcycles.tautgens(g, n, d)
222
gen_dual = admcycles.admcycles.tautgens(g, n, d_dual)
223
M_intpair = []
224
225
for i in ind:
226
intersection_vector = [(gen[i] * X).evaluate() for X in gen_dual]
227
M_intpair.append(intersection_vector)
228
Sol = list(matrix(M_intpair).solve_left(matrix(list_evaluate)))[0]
229
output = sum(Sol[i] * gen[ind[i]] for i in range(0, len(ind)))
230
return output
231
232
233
def solve_clutch_pullback(g, n, d, bdiv_indices, pullback_classes):
234
r"""
235
Identify a tautological class in degree d by specifying its pullback
236
under boundary gluing morphisms.
237
238
INPUT::
239
240
241
- bdiv_indices(list) : the list of indices of boundary
242
stratum(the first nontrivial graph in
243
tautgen list will be indexed
244
by 0) to which we will pullback
245
- pullback_classes(list) : the list of pullbacks of the tautological
246
class with respect to the bdiv listed
247
248
EXAMPLES::
249
250
sage: from admcycles.identify_classes import solve_clutch_pullback
251
sage: from admcycles import TautologicalRing
252
sage: R = TautologicalRing(1,3)
253
sage: stgraphs = [list(x._terms)[0] for x in R.generators(1)[4:]]
254
sage: cl = R.psi(1) -2 * R.kappa(1)
255
sage: def pullf(gr):
256
....: return gr.boundary_pullback(cl)
257
sage: cl2 = solve_clutch_pullback(1, 3, 1, range(len(stgraphs)),
258
....: [pullf(gr) for gr in stgraphs])
259
sage: cl == cl2
260
True
261
262
"""
263
264
if 2 * d > 2 * g - 2 + n:
265
print(" It may not work because the codim is too large")
266
ListV = [T.totensorTautbasis(d, vecout=True) for T in pullback_classes]
267
ListM = Pullback_Matrices(g, n, d)
268
ListM_1 = [ListM[i] for i in bdiv_indices]
269
Sol = SolveMultLin(ListM_1, ListV)
270
ind = admcycles.admcycles.generating_indices(g, n, d)
271
gen = admcycles.admcycles.tautgens(g, n, d)
272
output = sum(Sol[i] * gen[ind[i]] for i in range(len(ind)))
273
return output
274
275
276
def SolveMultLin(ListM, ListV):
277
278
dim = ListM[0].nrows()
279
assert all(Q.nrows() == dim for Q in ListM)
280
NewM = []
281
NewV = []
282
for Q in ListM:
283
NewM += list(Q.transpose())
284
NewM = matrix(NewM).transpose()
285
for W in ListV:
286
NewV += list(W)
287
NewV = matrix([NewV])
288
result = NewM.solve_left(NewV)
289
L = list(result)
290
Sol = vector(L[0])
291
return Sol
292
293