Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
181 views
unlisted
ubuntu2004
1
r"""
2
Multiplication in the strata algebra.
3
"""
4
5
import itertools
6
7
from sage.misc.cachefunc import cached_function
8
from sage.rings.integer_ring import ZZ
9
from sage.modules.free_module_element import vector
10
11
12
from .graph import Graph, R, X, all_strata, all_pure_strata, num_strata, single_stratum, unpurify_map, contraction_table, pure_strata_autom_count, automorphism_cosets, graph_isomorphic, num_of_stratum
13
from .moduli import MODULI_SM, MODULI_CT, MODULI_ST, MODULI_SMALL, dim_form
14
from .utils import simplify_sparse, setparts_with_auts
15
16
17
def get_marks(n, symm):
18
if symm == 0:
19
return tuple(range(1, n + 1))
20
return (1,) * symm + tuple(range(2, n - symm + 2))
21
22
23
@cached_function
24
def multiply(r1, i1, r2, i2, g, rmax, markings=(), moduli_type=MODULI_ST):
25
r"""
26
Return the result of the multiplication of the ``(r1, i1)``-th generator
27
with the ``(r2, i2)`` one.
28
29
The output is a list representing the coefficients with respect to the
30
generators in rank ``r1+r2``.
31
32
EXAMPLES::
33
34
sage: from admcycles.DR.graph import num_strata
35
sage: from admcycles.DR.algebra import multiply
36
sage: r1 = 1
37
sage: r2 = 2
38
sage: for i1 in range(num_strata(2, r1)):
39
....: for i2 in range(num_strata(2, r2)):
40
....: print(i1, i2, multiply(r1, i1, r2, i2, 2, r1 + r2))
41
0 0 [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
42
0 1 [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
43
0 2 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
44
0 3 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
45
0 4 [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
46
0 5 [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
47
0 6 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
48
0 7 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
49
1 0 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
50
1 1 [0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
51
1 2 [0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
52
1 3 [0, 0, 0, 0, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
53
1 4 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0]
54
1 5 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
55
1 6 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, 0, 0, 0]
56
1 7 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0]
57
2 0 [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
58
2 1 [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
59
2 2 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
60
2 3 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0]
61
2 4 [0, 0, 0, 0, 0, 0, 0, 0, -4, 0, 0, 0, 0, 1, 0, 0, 0]
62
2 5 [0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, 0, 0, 0, 1, 0, 0]
63
2 6 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
64
2 7 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -8, 0, 4]
65
"""
66
unpurify = unpurify_map(g, r1 + r2, markings, moduli_type)
67
gens = all_strata(g, r1 + r2, markings, moduli_type)
68
ngens = num_strata(g, r1 + r2, markings, moduli_type)
69
answer = [0 for i in range(ngens)]
70
pure_strata = [all_pure_strata(g, r, markings, moduli_type)
71
for r in range(rmax + 1)]
72
contraction_dict = contraction_table(g, rmax, markings, moduli_type)
73
G1 = single_stratum(i1, g, r1, markings, moduli_type)
74
G2 = single_stratum(i2, g, r2, markings, moduli_type)
75
G1copy = Graph(G1.M)
76
G2copy = Graph(G2.M)
77
G1copy.purify()
78
G2copy.purify()
79
pure_r1 = G1copy.num_edges() - len(markings)
80
pure_r2 = G2copy.num_edges() - len(markings)
81
found = False
82
for i in range(len(pure_strata[pure_r1])):
83
if G1copy.M == pure_strata[pure_r1][i].M:
84
G1_key = (pure_r1, i)
85
found = True
86
break
87
assert found, "G1 purification failed"
88
found = False
89
for i in range(len(pure_strata[pure_r2])):
90
if G2copy.M == pure_strata[pure_r2][i].M:
91
G2_key = (pure_r2, i)
92
found = True
93
break
94
assert found, "G2 purification failed"
95
if G1_key > G2_key:
96
return multiply(r2, i2, r1, i1, g, rmax, markings, moduli_type)
97
98
if (G1_key, G2_key) not in contraction_dict:
99
return answer
100
for L in contraction_dict[(G1_key, G2_key)]:
101
H = pure_strata[L[0][0]][L[0][1]]
102
Hloops = []
103
if moduli_type > MODULI_CT:
104
for i in range(1, H.M.nrows()):
105
for j in range(1, H.M.ncols()):
106
if H.M[i, j][0] == 2:
107
Hloops.append((i, j))
108
auts = pure_strata_autom_count(
109
L[0][1], g, L[0][0], markings, moduli_type)
110
B = L[1]
111
if len(B) == pure_r1 and len(B) == pure_r2:
112
auts *= 2
113
aut_cosets1 = automorphism_cosets(i1, g, r1, markings, moduli_type)
114
aut_cosets2 = automorphism_cosets(i2, g, r2, markings, moduli_type)
115
auts /= aut_cosets1[0] * aut_cosets2[0]
116
for isom1 in aut_cosets1[1]:
117
for isom2 in aut_cosets2[1]:
118
Hcopy = Graph(H.M)
119
vmap1 = [0 for i in range(G1.M.nrows())]
120
for i in range(1, G1.M.nrows()):
121
vmap1[i] = L[2][0][L[4][0][isom1[0]
122
[i - 1] - 1] - 1]
123
emap1 = [0 for i in range(G1.M.ncols())]
124
for i in range(1, G1.M.ncols()):
125
emap1[i] = L[2][1][L[4][1][isom1[1]
126
[i - 1] - 1] - 1]
127
vmap2 = [0 for i in range(G2.M.nrows())]
128
for i in range(1, G2.M.nrows()):
129
vmap2[i] = L[3][0][L[5][0][isom2[0]
130
[i - 1] - 1] - 1]
131
emap2 = [0 for i in range(G2.M.ncols())]
132
for i in range(1, G2.M.ncols()):
133
emap2[i] = L[3][1][L[5][1][isom2[1]
134
[i - 1] - 1] - 1]
135
136
psilooplist = []
137
psiindexlist = []
138
loop_factor = ZZ.one()
139
for i in range(1, G1.M.nrows()):
140
for j in range(1, G1.M.ncols()):
141
if G1.M[i, j][0] != 0:
142
if G1.M[i, j][0] == 1:
143
if G1.M[i, j][1] != 0:
144
jj = emap1[j]
145
for ii in vmap1[i]:
146
if H.M[ii, jj] != 0:
147
Hcopy.M[ii, jj] += G1.M[i, j][1] * X
148
break
149
elif G1.M[i, j][1] == 0:
150
loop_factor *= 2
151
else:
152
jj = emap1[j]
153
psilooplist.append([[G1.M[i, j][1], G1.M[i, j][2]], [
154
G1.M[i, j][2], G1.M[i, j][1]]])
155
psiindexlist.append([jj])
156
for ii in vmap1[i]:
157
for k in range(H.M[ii, jj][0]):
158
psiindexlist[-1].append(ii)
159
for i in range(1, G2.M.nrows()):
160
for j in range(1, G2.M.ncols()):
161
if G2.M[i, j][0] != 0:
162
if G2.M[i, j][0] == 1:
163
if G2.M[i, j][1] != 0:
164
if G2.M[i, j][0] == 1:
165
jj = emap2[j]
166
for ii in vmap2[i]:
167
if H.M[ii, jj] != 0:
168
Hcopy.M[ii,
169
jj] += G2.M[i, j][1] * X
170
break
171
elif G2.M[i, j][1] == 0:
172
loop_factor *= 2
173
else:
174
jj = emap2[j]
175
psilooplist.append([[G2.M[i, j][1], G2.M[i, j][2]], [
176
G2.M[i, j][2], G2.M[i, j][1]]])
177
psiindexlist.append([jj])
178
for ii in vmap2[i]:
179
for k in range(H.M[ii, jj][0]):
180
psiindexlist[-1].append(ii)
181
182
Klocationlist = []
183
Kindexlist = []
184
for i in range(1, G1.M.nrows()):
185
for r in range(1, rmax + 1):
186
for k in range(G1.M[i, 0][r]):
187
Klocationlist.append(vmap1[i])
188
Kindexlist.append(r)
189
for i in range(1, G2.M.nrows()):
190
for r in range(1, rmax + 1):
191
for k in range(G2.M[i, 0][r]):
192
Klocationlist.append(vmap2[i])
193
Kindexlist.append(r)
194
195
psilist = []
196
for j in B:
197
S = [i for i in range(1, H.M.nrows()) if H.M[i, j][0] != 0]
198
if len(S) == 2:
199
psilist.append([[S[0], j], [S[1], j]])
200
else:
201
psilooplist.append([[0, 1], [1, 0]])
202
psiindexlist.append([j, S[0], S[0]])
203
204
for psiloopvals in itertools.product(*psilooplist):
205
for Klocs in itertools.product(*Klocationlist):
206
for psilocs in itertools.product(*psilist):
207
Hcopycopy = Graph(Hcopy.M)
208
for i in range(len(psiindexlist)):
209
Hcopycopy.M[psiindexlist[i][1],
210
psiindexlist[i][0]] += psiloopvals[i][0] * X
211
if psiindexlist[i][1] == psiindexlist[i][2]:
212
Hcopycopy.M[psiindexlist[i][1],
213
psiindexlist[i][0]] += psiloopvals[i][1] * X**2
214
else:
215
Hcopycopy.M[psiindexlist[i][2],
216
psiindexlist[i][0]] += psiloopvals[i][1] * X
217
for i in range(len(Kindexlist)):
218
Hcopycopy.M[Klocs[i],
219
0] += X**Kindexlist[i]
220
for i in psilocs:
221
Hcopycopy.M[i[0], i[1]] += X
222
for k in Hloops:
223
if Hcopycopy.M[k][2] > Hcopycopy.M[k][1]:
224
Hcopycopy.M[k] += (Hcopycopy.M[k]
225
[2] - Hcopycopy.M[k][1]) * (X - X**2)
226
Hcopycopy.compute_invariant()
227
for which_gen in unpurify[L[0]]:
228
if graph_isomorphic(Hcopycopy, gens[which_gen]):
229
answer[which_gen] += (-1)**len(B) * \
230
loop_factor / auts
231
break
232
return answer
233
234
235
def check_associativity(g, r1, r2, r3, markings=(), moduli_type=MODULI_ST):
236
r"""
237
Check associativity of the strata algebra.
238
239
If it fails a ``ValueError`` is raised.
240
241
EXAMPLES::
242
243
sage: from admcycles.DR.algebra import check_associativity
244
sage: check_associativity(2, 1, 1, 1)
245
"""
246
ngens1 = num_strata(g, r1, markings, moduli_type)
247
ngens2 = num_strata(g, r2, markings, moduli_type)
248
ngens3 = num_strata(g, r3, markings, moduli_type)
249
for i1, i2, i3 in itertools.product(range(ngens1), range(ngens2), range(ngens3)):
250
a = multiply(r1, i1, r2, i2, g, r1 + r2 +
251
r3, markings, moduli_type)
252
answer1 = vector(
253
[0 for i in range(num_strata(g, r1 + r2 + r3, markings, moduli_type))])
254
for j in range(num_strata(g, r1 + r2, markings, moduli_type)):
255
if a[j] == 0:
256
continue
257
answer1 += a[j] * vector(multiply(r1 + r2, j, r3,
258
i3, g, r1 + r2 + r3, markings, moduli_type))
259
a = multiply(r1, i1, r3, i3, g, r1 + r2 +
260
r3, markings, moduli_type)
261
answer2 = vector(
262
[0 for i in range(num_strata(g, r1 + r2 + r3, markings, moduli_type))])
263
for j in range(num_strata(g, r1 + r3, markings, moduli_type)):
264
if a[j] == 0:
265
continue
266
answer2 += a[j] * vector(multiply(r1 + r3, j, r2,
267
i2, g, r1 + r2 + r3, markings, moduli_type))
268
if answer1 != answer2:
269
raise ValueError("i1=%s i2=%s i3=%s" % (i1, i2, i3))
270
271
272
@cached_function
273
def kappa_conversion(sigma):
274
r"""
275
EXAMPLES::
276
277
sage: from admcycles.DR.algebra import kappa_conversion
278
sage: kappa_conversion((1, 1, 1))
279
[[3*X, 1], [X^2 + X, 3], [X^3, 2]]
280
"""
281
answer = []
282
for spart in setparts_with_auts(list(sigma)):
283
coeff = spart[1]
284
poly = R(0)
285
for part in spart[0]:
286
coeff *= ZZ(len(part) - 1).factorial()
287
poly += X**sum(part)
288
answer.append([poly, coeff])
289
return answer
290
291
292
@cached_function
293
def kappa_conversion_inverse(sigma):
294
r"""
295
EXAMPLES::
296
297
sage: from admcycles.DR.algebra import kappa_conversion_inverse
298
sage: kappa_conversion_inverse((1, 1, 1))
299
[[3*X, 1], [X^2 + X, -3], [X^3, 1]]
300
"""
301
answer = []
302
for spart in setparts_with_auts(list(sigma)):
303
coeff = spart[1] * (-1)**(len(sigma) - len(spart[0]))
304
poly = R(0)
305
for part in spart[0]:
306
poly += X**sum(part)
307
answer.append([poly, coeff])
308
return answer
309
310
311
@cached_function
312
def convert_to_monomial_basis(num, g, r, markings=(), moduli_type=MODULI_ST):
313
r"""
314
EXAMPLES::
315
316
sage: from admcycles.DR.algebra import convert_to_monomial_basis
317
318
sage: convert_to_monomial_basis(1, 2, 3, (1, 2, 3))
319
[(1, 1), (0, 1)]
320
sage: convert_to_monomial_basis(2, 2, 3, (1, 2, 3))
321
[(2, 1), (1, 3), (0, 2)]
322
"""
323
answer = []
324
G = single_stratum(num, g, r, markings, moduli_type)
325
genus_vec = []
326
kappa_vec = []
327
for i in range(1, G.M.nrows()):
328
genus_vec.append(G.M[i, 0][0])
329
kappa_vec.append([])
330
for j in range(1, r + 1):
331
for k in range(G.M[i, 0][j]):
332
kappa_vec[-1].append(j)
333
kappa_vec[-1] = kappa_conversion(tuple(kappa_vec[-1]))
334
for choice in itertools.product(*kappa_vec):
335
coeff = 1
336
GG = Graph(G.M)
337
for i in range(1, G.M.nrows()):
338
GG.M[i, 0] = genus_vec[i - 1] + choice[i - 1][0]
339
coeff *= choice[i - 1][1]
340
answer.append((num_of_stratum(GG, g, r, markings, moduli_type), coeff))
341
return answer
342
343
344
# NOTE: this function is not used anywhere
345
@cached_function
346
def convert_to_pushforward_basis(num, g, r, markings=(), moduli_type=MODULI_ST):
347
answer = []
348
G = single_stratum(num, g, r, markings, moduli_type)
349
genus_vec = []
350
kappa_vec = []
351
for i in range(1, G.M.nrows()):
352
genus_vec.append(G.M[i, 0][0])
353
kappa_vec.append([])
354
for j in range(1, r + 1):
355
for k in range(G.M[i, 0][j]):
356
kappa_vec[-1].append(j)
357
kappa_vec[-1] = kappa_conversion_inverse(
358
tuple(kappa_vec[-1]))
359
for choice in itertools.product(*kappa_vec):
360
coeff = 1
361
GG = Graph(G.M)
362
for i in range(1, G.M.nrows()):
363
GG.M[i, 0] = genus_vec[i - 1] + choice[i - 1][0]
364
coeff *= choice[i - 1][1]
365
answer.append((num_of_stratum(GG, g, r, markings, moduli_type), coeff))
366
return answer
367
368
369
def convert_vector_to_monomial_basis(vec, g, r, markings=(), moduli_type=MODULI_ST):
370
r"""
371
EXAMPLES::
372
373
sage: from admcycles.DR.moduli import MODULI_SM, MODULI_RT, MODULI_CT, MODULI_ST
374
sage: from admcycles.DR.algebra import convert_vector_to_monomial_basis
375
sage: convert_vector_to_monomial_basis(vec=(-24504480, 1663200, -36000), g=8, r=3, markings=(), moduli_type=MODULI_SM)
376
[-22913280, 1555200, -36000]
377
sage: convert_vector_to_monomial_basis(vec=(0, 0, -15, 0, 15, 15, 0, 0, 0), g=2, r=2, markings=(1, 2), moduli_type=MODULI_RT)
378
[0, 0, -15, 0, 15, 15, 0, 0, 0]
379
sage: convert_vector_to_monomial_basis(vec=(71820, -7020, 9720, -41580, 9288, -3240, -18900, 756), g=2, r=2, markings=(1,), moduli_type=MODULI_CT)
380
[64800, -7020, 9720, -41580, 9288, -3240, -18900, 756]
381
sage: convert_vector_to_monomial_basis(vec=(81/2, -45/2, -45/2, -45/2, 9/2, 9/2, 9/2, -27/2, -9/4), g=1, r=1, markings=(1, 2, 3), moduli_type=MODULI_ST)
382
[81/2, -45/2, -45/2, -45/2, 9/2, 9/2, 9/2, -27/2, -9/4]
383
"""
384
l = len(vec)
385
vec2 = [0 for i in range(l)]
386
for i in range(l):
387
if vec[i] != 0:
388
for x in convert_to_monomial_basis(i, g, r, markings, moduli_type):
389
vec2[x[0]] += x[1] * vec[i]
390
return vec2
391
392
393
# NOTE: this function is not used anywhere
394
def convert_vector_to_pushforward_basis(vec, g, r, markings=(), moduli_type=MODULI_ST):
395
l = len(vec)
396
vec2 = [0 for i in range(l)]
397
for i in range(l):
398
if vec[i] != 0:
399
for x in convert_to_pushforward_basis(i, g, r, markings, moduli_type):
400
vec2[x[0]] += x[1] * vec[i]
401
return vec2
402
403
404
def kappa_multiple(vec, which_kappa, g, r, n, symm, moduli_type=MODULI_ST):
405
r"""
406
Return the multiplication of the sparse vector ``vec`` by a kappa-class.
407
"""
408
vec2 = []
409
for num, coeff in vec:
410
for num2, coeff2 in single_kappa_multiple(num, which_kappa, g, r, n, symm, moduli_type):
411
vec2.append([num2, coeff * coeff2])
412
return simplify_sparse(vec2)
413
414
415
# TODO: why using (n, symm) rather than a tuple of markings here?
416
def psi_multiple(vec, which_psi, g, r, n, symm, moduli_type=MODULI_ST):
417
r"""
418
Return the multiplication of the sparse vector ``vec`` by a psi-class.
419
"""
420
vec2 = []
421
for num, coeff in vec:
422
for num2, coeff2 in single_psi_multiple(num, which_psi, g, r, n, symm, moduli_type):
423
vec2.append([num2, coeff * coeff2])
424
return simplify_sparse(vec2)
425
426
427
# TODO: why using (n, symm) rather than a tuple of markings here?
428
def insertion_pullback(vec, new_mark, g, r, n, symm, moduli_type=MODULI_ST, from_small=False):
429
r"""
430
For a relation ``vec`` we return its pullback along the forgetfulmap that forgets a point.
431
"""
432
vec2 = []
433
for x in vec:
434
for y in single_insertion_pullback(x[0], new_mark, g, r, n, symm, moduli_type, from_small):
435
vec2.append([y[0], x[1] * y[1]])
436
return simplify_sparse(vec2)
437
438
439
# TODO: why using (n, symm) rather than a tuple of markings here?
440
@cached_function
441
def single_psi_multiple(num, which_psi, g, r, n, symm, moduli_type=MODULI_ST):
442
r"""
443
Takes the index of a stratum ``num`` and returns the stratum in degree ``r+1``
444
(as a sparse vector of length 1) corresponding to its multiplication by a psi-class.
445
446
EXAMPLES::
447
448
sage: from admcycles.DR.moduli import MODULI_RT, MODULI_CT, MODULI_ST
449
sage: from admcycles.DR.algebra import single_psi_multiple
450
sage: single_psi_multiple(5, 1, 2, 2, 2, 0, MODULI_ST)
451
[(11, 1)]
452
"""
453
markings = get_marks(n, symm)
454
G = single_stratum(num, g, r, markings, moduli_type)
455
answer = []
456
for j in range(1, G.M.ncols()):
457
if G.M[0, j] == which_psi:
458
good_j = j
459
break
460
for i in range(1, G.M.nrows()):
461
if G.M[i, good_j] != 0:
462
deg = 0
463
dim_used = 0
464
for j in range(1, r + 1):
465
dim_used += j * G.M[i, 0][j]
466
for j in range(1, G.M.ncols()):
467
dim_used += G.M[i, j][1] + G.M[i, j][2]
468
deg += G.M[i, j][0]
469
if dim_used < dim_form(G.M[i, 0][0], deg, moduli_type):
470
GG = Graph(G.M)
471
GG.M[i, good_j] += X
472
answer.append(
473
(num_of_stratum(GG, g, r + 1, markings, moduli_type), 1))
474
break
475
return answer
476
477
478
# TODO: why using (n, symm) rather than a tuple of markings here?
479
@cached_function
480
def single_kappa_multiple(num, which_kappa, g, r, n, symm, moduli_type=MODULI_ST):
481
r"""
482
Takes the index of a stratum ``num`` and returns the index of its multiplication by a kappa-class.
483
This uses the multi-indexed pushforward kappa-classes, rather than monomials in kappa-classes.
484
"""
485
markings = get_marks(n, symm)
486
G = single_stratum(num, g, r, markings, moduli_type)
487
answer = []
488
for i in range(1, G.M.nrows()):
489
deg = 0
490
dim_used = 0
491
for j in range(1, r + 1):
492
dim_used += j * G.M[i, 0][j]
493
for j in range(1, G.M.ncols()):
494
dim_used += G.M[i, j][1] + G.M[i, j][2]
495
deg += G.M[i, j][0]
496
if dim_used + which_kappa <= dim_form(G.M[i, 0][0], deg, moduli_type):
497
GG = Graph(G.M)
498
GG.M[i, 0] += X**which_kappa
499
answer.append((num_of_stratum(GG, g, r + which_kappa,
500
markings, moduli_type), 1))
501
for j in range(1, r + 1):
502
if G.M[i, 0][j] > 0:
503
GG = Graph(G.M)
504
GG.M[i, 0] += X**(j + which_kappa)
505
GG.M[i, 0] -= X**j
506
answer.append((num_of_stratum(
507
GG, g, r + which_kappa, markings, moduli_type), -G.M[i, 0][j]))
508
return answer
509
510
511
# NOTE: this function is not used anywhere
512
def single_kappa_psi_multiple(num, kappa_partition, psi_exps, g, r, n=0, moduli_type=MODULI_ST):
513
markings = tuple(range(1, n + 1))
514
G = single_stratum(num, g, r, markings, moduli_type)
515
GG = Graph(G.M)
516
for j in range(1, G.M.ncols()):
517
if GG.M[0, j] != 0:
518
for i in range(1, G.M.nrows()):
519
if GG.M[i, j] != 0:
520
GG.M[i, j] += psi_exps[GG.M[0, j][0] - 1] * X
521
break
522
rnew = r + sum(kappa_partition) + sum(psi_exps)
523
answer = []
524
kappa_options = [list(range(1, G.M.nrows()))
525
for i in range(len(kappa_partition))]
526
for kappa_distrib in itertools.product(*kappa_options):
527
GGG = Graph(GG.M)
528
for i in range(len(kappa_partition)):
529
GGG.M[kappa_distrib[i], 0] += X**(kappa_partition[i])
530
is_bad = False
531
for i in range(1, GGG.M.nrows()):
532
deg = 0
533
dim_used = 0
534
for j in range(1, rnew + 1):
535
dim_used += j * GGG.M[i, 0][j]
536
for j in range(1, GGG.M.ncols()):
537
dim_used += GGG.M[i, j][1] + GGG.M[i, j][2]
538
deg += GGG.M[i, j][0]
539
if dim_used > dim_form(GGG.M[i, 0][0], deg, moduli_type):
540
is_bad = True
541
break
542
if is_bad:
543
continue
544
answer.append(
545
(num_of_stratum(GGG, g, rnew, markings, moduli_type), 1))
546
return answer
547
548
549
# TODO: why using (n, symm) rather than markings here?
550
@cached_function
551
def single_insertion_pullback(num, new_mark, g, r, n, symm, moduli_type=MODULI_ST, from_small=False):
552
r"""
553
Takes the index of a stratum ``num`` and returns the sparse vector
554
representation of its pullback along the forgetfulmap that foregets a
555
point.
556
557
EXAMPLES::
558
559
sage: from admcycles.DR.algebra import single_insertion_pullback
560
561
sage: single_insertion_pullback(0, 1, 5, 2, 0, 0, 1, False)
562
[(0, 1), (3, -1)]
563
sage: single_insertion_pullback(1, 1, 5, 2, 0, 0, 1, False)
564
[(1, 1), (2, -1), (2, -1)]
565
sage: single_insertion_pullback(10, 1, 2, 2, 1, 0, 3, False)
566
[(25, 1), (27, -1)]
567
"""
568
markings = get_marks(n, symm)
569
if new_mark == 1:
570
new_markings = get_marks(n + 1, symm + 1)
571
else:
572
new_markings = get_marks(n + 1, symm)
573
if from_small:
574
G = single_stratum(num, g, r, markings, MODULI_SMALL)
575
else:
576
G = single_stratum(num, g, r, markings, moduli_type)
577
answer = []
578
for i in range(1, G.M.nrows()):
579
GG = Graph(G.M)
580
if not (new_mark == 1 and symm > 0):
581
for j in range(1, G.M.ncols()):
582
if GG.M[0, j][0] >= new_mark:
583
GG.M[0, j] += 1
584
GG.add_edge(i, 0, new_mark)
585
answer.append(
586
(num_of_stratum(GG, g, r, new_markings, moduli_type), 1))
587
for j in range(1, r + 1):
588
for k in range(GG.M[i, 0][j]):
589
GGG = Graph(GG.M)
590
GGG.M[i, 0] -= X**j
591
GGG.M[i, -1] += j * X
592
answer.append(
593
(num_of_stratum(GGG, g, r, new_markings, moduli_type), -1))
594
if moduli_type <= MODULI_SM:
595
continue
596
for j in range(1, G.M.ncols()):
597
if G.M[i, j][0] == 1:
598
if G.M[i, j][1] >= 1:
599
x = G.M[i, j][1]
600
GGG = Graph(GG.M)
601
row1 = [GG.M[i, k] for k in range(GG.M.ncols())]
602
row2 = [0 for k in range(GG.M.ncols())]
603
row1[j] = 0
604
row1[-1] = 0
605
row2[j] = 1
606
row2[-1] = 1
607
GGG.split_vertex(i, row1, row2)
608
GGG.M[-2, -
609
1] += (x - 1) * X
610
answer.append(
611
(num_of_stratum(GGG, g, r, new_markings, moduli_type), -1))
612
if not from_small:
613
if G.M[i, j][0] == 2:
614
if G.M[i, j][1] >= 1 or G.M[i, j][2] >= 1:
615
x = G.M[i, j][1]
616
y = G.M[i, j][2]
617
row1 = [GG.M[i, k] for k in range(GG.M.ncols())]
618
row2 = [0 for k in range(GG.M.ncols())]
619
row1[j] = 0
620
row1[-1] = 0
621
row2[j] = 1
622
row2[-1] = 1
623
if y >= 1:
624
row1[j] = 1 + x * X
625
GGG = Graph(GG.M)
626
GGG.split_vertex(i, row1, row2)
627
GGG.M[-2, -
628
1] += (y - 1) * X
629
answer.append(
630
(num_of_stratum(GGG, g, r, new_markings, moduli_type), -1))
631
if x >= 1:
632
row1[j] = 1 + y * X
633
GGG = Graph(GG.M)
634
GGG.split_vertex(i, row1, row2)
635
GGG.M[-2, -
636
1] += (x - 1) * X
637
answer.append(
638
(num_of_stratum(GGG, g, r, new_markings, moduli_type), -1))
639
return answer
640
641