Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
181 views
unlisted
ubuntu2004
1
import sys
2
3
from itertools import product
4
5
from sage.rings.rational_field import QQ # pylint: disable=import-error
6
from sage.arith.functions import lcm # pylint: disable=import-error
7
from sage.arith.misc import gcd # pylint: disable=import-error
8
from sage.symbolic.ring import SR # pylint: disable=import-error
9
from sage.matrix.constructor import Matrix # pylint: disable=import-error
10
from sage.modules.free_module_element import free_module_element # pylint: disable=import-error
11
from sage.combinat.integer_vector_weighted import WeightedIntegerVectors # pylint: disable=import-error
12
from sage.misc.cachefunc import cached_method # pylint: disable=import-error
13
14
from admcycles.diffstrata.generalisedstratum import GeneralisedStratum, Stratum
15
from admcycles.diffstrata.sig import Signature
16
17
import admcycles.admcycles
18
19
20
def test_calL(sig):
21
"""
22
Compare calL and the 'error term' of cnb.
23
24
EXAMPLES::
25
26
sage: from admcycles.diffstrata.tests import test_calL
27
sage: test_calL((1,1,1,1,-6))
28
sage: test_calL((4,))
29
"""
30
X = GeneralisedStratum([Signature(sig)])
31
for i, B in enumerate(X.bics):
32
ll = lcm(B.LG.prongs.values())
33
assert X.calL(((i,), 0), 0) + ll * X.cnb(((i,), 0), ((i,), 0)) + X.gen_pullback_taut(X.xi_at_level(0, ((i,), 0)),
34
((i,), 0), ((i,), 0)) + (-1) * X.gen_pullback_taut(X.xi_at_level(1, ((i,), 0)), ((i,), 0), ((i,), 0)) == X.ZERO
35
36
37
def meromorphic_tests():
38
"""
39
EXAMPLES::
40
41
sage: from admcycles.diffstrata import *
42
sage: X=GeneralisedStratum([Signature((1,1,1,1,-6))])
43
sage: (X.xi^2).evaluate(quiet=True)
44
25
45
46
sage: X=GeneralisedStratum([Signature((-2,-2,-2,-2,6))])
47
sage: (X.xi^X.dim()).evaluate(quiet=True)
48
30
49
50
Testing normal bundles:
51
52
sage: X=GeneralisedStratum([Signature((2,2,-2))])
53
sage: td0 = X.taut_from_graph((0,))
54
sage: td1 = X.taut_from_graph((1,))
55
sage: td4 = X.taut_from_graph((4,))
56
sage: td5 = X.taut_from_graph((5,))
57
sage: td8 = X.taut_from_graph((8,))
58
sage: assert X.ZERO == td0^2*td1 - td0*td1*td0 # not 'safe' # doctest:+SKIP
59
sage: assert X.ZERO == td0^2*td5 - td0*td5*td0 # not 'safe' # doctest:+SKIP
60
sage: assert X.ZERO == td0^2*td8 - td0*td8*td0 # not 'safe' # doctest:+SKIP
61
sage: assert (td8^3*td4).evaluate(quiet=True) == (td8^2*td4*td8).evaluate(quiet=True) == (td8*td4*td8^2).evaluate(quiet=True)
62
63
"""
64
pass
65
66
67
def gengenustwotests():
68
"""
69
EXAMPLES::
70
71
sage: from admcycles.diffstrata import *
72
sage: X=GeneralisedStratum([Signature((2,))])
73
sage: assert (X.xi^X.dim()).evaluate(quiet=True) == -1/640
74
sage: ct=[i for i, B in enumerate(X.bics) if len(B.LG.edges) == 1]
75
sage: ct_index = ct[0] # compact type graph
76
sage: ct_taut = X.taut_from_graph((ct_index,))
77
sage: assert (X.c2_E*ct_taut).evaluate(quiet=True) == 1/48
78
sage: banana_index = 1 - ct_index # only 2 BICs!
79
sage: banana_taut = X.taut_from_graph((banana_index,))
80
sage: assert (X.c2_E*banana_taut).evaluate(quiet=True) == 1/24
81
sage: assert (X.c1_E*banana_taut**2).evaluate(quiet=True) == -1/16
82
sage: assert (X.c1_E*banana_taut*ct_taut).evaluate(quiet=True) == 1/24
83
sage: assert (X.c1_E*ct_taut**2).evaluate(quiet=True) == -1/48
84
sage: assert (ct_taut**3).evaluate(quiet=True) == 1/96
85
sage: assert (banana_taut**3).evaluate(quiet=True) == 1/48
86
sage: assert (ct_taut*banana_taut**2).evaluate(quiet=True) == 0
87
sage: assert (ct_taut*ct_taut*banana_taut).evaluate(quiet=True) == -1/48
88
89
sage: X=GeneralisedStratum([Signature((1,1))])
90
sage: at1 = X.taut_from_graph((1,))
91
sage: at2 = X.taut_from_graph((2,))
92
sage: X.ZERO == at1^2*at2 + (-1)*at1*at2*at1
93
True
94
sage: X.ZERO == (-1)*(at1+at2)^3*at2 + at1^3*at2 + 3*at1^2*at2*at2 + 3*at1*at2^2*at2 + at2^3*at2
95
True
96
sage: X.ZERO == (-1)*(at1+at2)^4 + at1^4 + 4*at1^3*at2 + 6*at1^2*at2^2 + 4*at1^1*at2^3 + at2^4
97
True
98
sage: (X.xi^X.dim()).evaluate(quiet=True)
99
0
100
sage: psi1 = AdditiveGenerator(X,((),0),{1:1}).as_taut()
101
sage: (X.xi^3*psi1).evaluate(quiet=True)
102
-1/360
103
"""
104
pass
105
106
107
def genusthreetests():
108
"""
109
Testing Normal bundles in min stratum (4):
110
111
EXAMPLES::
112
113
sage: from admcycles.diffstrata import *
114
sage: X=GeneralisedStratum([Signature((4,))])
115
116
sage: v_banana = [i for i, B in enumerate(X.bics) if B.LG.genera == [1,1,0]]
117
sage: v_banana_taut=X.taut_from_graph((v_banana[0],))
118
sage: g1_banana = [i for i, B in enumerate(X.bics) if B.LG.genera == [1,1]]
119
sage: g1_banana_taut=X.taut_from_graph((g1_banana[0],))
120
121
sage: assert g1_banana_taut**2*v_banana_taut + (-1)*g1_banana_taut*v_banana_taut*g1_banana_taut == X.ZERO
122
sage: assert v_banana_taut**2*g1_banana_taut + (-1)*v_banana_taut*g1_banana_taut*v_banana_taut == X.ZERO
123
124
sage: (X.xi_with_leg(quiet=True)^X.dim()).evaluate(quiet=True) # long time # optional - local
125
305/580608
126
"""
127
pass
128
129
130
def genusfourtests():
131
"""
132
Tests in H(6): (think of smart NB test...)
133
134
EXAMPLES::
135
136
sage: from admcycles.diffstrata import *
137
138
"""
139
pass
140
141
142
class BananaSuite:
143
"""
144
A frontend for the Stratum (k, 1, -k-1).
145
146
This class models the situation of sec 10.2 of CMZ20
147
with a method D for accessing the divisors in the
148
notation of loc. cit. (either D(i), i=2,3,4 or D(i,a)
149
for i=1,5).
150
"""
151
152
def __init__(self, k):
153
"""
154
Initialise the genus 1 stratum (k, 1, -k-1).
155
156
Args:
157
k (int): order of zero
158
"""
159
self._k = k
160
self._X = GeneralisedStratum([Signature((k, 1, -k - 1))])
161
162
def D(self, i, a=1):
163
"""
164
The divisor using the notation of Sec. 10.2.
165
166
Args:
167
i (int): index 1,2,3,4,5
168
a (int, optional): prong for i=1 or 5. Defaults to 1.
169
170
Returns:
171
ELGTautClass: Tautological class of the divisor D_{i,a}.
172
"""
173
if i == 1:
174
for b, B in enumerate(self._X.bics):
175
v = B.LG.verticesonlevel(0)[0]
176
if (B.LG.genus(v) == 0 and
177
len(B.LG.ordersonvertex(v)) == 3 and
178
len(B.LG.edges) == 2 and
179
a in B.LG.prongs.values()):
180
assert -self._k - 1 in B.LG.ordersonvertex(v),\
181
"%r" % B
182
return self._X.taut_from_graph((b,))
183
elif i == 2:
184
for b, B in enumerate(self._X.bics):
185
v = B.LG.verticesonlevel(0)[0]
186
if (B.LG.genus(v) == 1 and len(B.LG.ordersonvertex(v)) == 2):
187
assert -self._k - 1 in B.LG.ordersonvertex(v),\
188
"%r" % B
189
return self._X.taut_from_graph((b,))
190
elif i == 3:
191
for b, B in enumerate(self._X.bics):
192
v = B.LG.verticesonlevel(0)[0]
193
if (B.LG.genus(v) == 1 and len(B.LG.ordersonvertex(v)) == 1):
194
return self._X.taut_from_graph((b,))
195
elif i == 4:
196
for b, B in enumerate(self._X.bics):
197
v = B.LG.verticesonlevel(-1)[0]
198
if (B.LG.genus(v) == 1 and len(B.LG.ordersonvertex(v)) == 2):
199
return self._X.taut_from_graph((b,))
200
elif i == 5:
201
for b, B in enumerate(self._X.bics):
202
v = B.LG.verticesonlevel(0)[0]
203
if (B.LG.genus(v) == 0 and
204
len(B.LG.ordersonvertex(v)) == 4 and
205
len(B.LG.edges) == 2 and
206
a in B.LG.prongs.values()):
207
assert -self._k - 1 in B.LG.ordersonvertex(v),\
208
"%r" % B
209
return self._X.taut_from_graph((b,))
210
else:
211
return None
212
213
def check(self, quiet=False):
214
"""
215
Check Prop 10.1
216
217
Args:
218
quiet (bool, optional): No output. Defaults to False.
219
220
Returns:
221
bool: Should always return True.
222
"""
223
check_list = []
224
225
def delta(k, a):
226
if a == k / 2:
227
return QQ(1) / QQ(2)
228
else:
229
return 1
230
for a in range(1, self._k + 1):
231
si = (self.D(1, a)**2).evaluate(quiet=True)
232
rhs = -QQ(delta(self._k + 1, a) * self._k *
233
gcd(a, self._k + 1 - a)) / QQ(lcm(a, self._k + 1 - a))
234
check_list.append(si == rhs)
235
if not quiet:
236
print("D(1,%r)^2 = %r, RHS = %r" % (a, si, rhs))
237
for a in range(1, self._k):
238
si = (self.D(5, a)**2).evaluate(quiet=True)
239
rhs = -QQ(delta(self._k, a) * (self._k + 1) *
240
gcd(a, self._k - a)) / QQ(lcm(a, self._k - a))
241
check_list.append(si == rhs)
242
if not quiet:
243
print("D(5,%r)^2 = %r, RHS = %r" % (a, si, rhs))
244
return all(check_list)
245
246
def banana_tests(self):
247
"""
248
EXAMPLES::
249
250
sage: from admcycles.diffstrata.tests import BananaSuite
251
sage: B=BananaSuite(2)
252
sage: B.check(quiet=True)
253
True
254
sage: (B._X.xi**2).evaluate(quiet=True) == QQ(2**4 - 1)/QQ(24)
255
True
256
sage: assert((B._X.xi_with_leg(quiet=True)*B.D(5,1)).evaluate(quiet=True) == \
257
B._X.xi_at_level(0,B.D(5,1).psi_list[0][1].enh_profile,quiet=True).evaluate(quiet=True) == -1)
258
sage: assert(B._X.xi_at_level(0,B.D(5,1).psi_list[0][1].enh_profile,leg=3,quiet=True).evaluate(quiet=True) == -1)
259
260
sage: B=BananaSuite(5)
261
sage: B.check(quiet=True)
262
True
263
sage: B=BananaSuite(5)
264
sage: (B._X.xi**2).evaluate(quiet=True) == QQ(5**4 - 1)/QQ(24)
265
True
266
267
sage: B=BananaSuite(6)
268
sage: assert((B._X.xi_with_leg(quiet=True)*B.D(5,2)).evaluate(quiet=True) == \
269
B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=1,quiet=True).evaluate(quiet=True) == \
270
B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=2,quiet=True).evaluate(quiet=True) == \
271
B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=3,quiet=True).evaluate(quiet=True) == \
272
B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=4,quiet=True).evaluate(quiet=True) == -12)
273
274
sage: B=BananaSuite(10)
275
sage: B.check(quiet=True)
276
True
277
sage: (B._X.xi**2).evaluate(quiet=True) == QQ(10**4 - 1)/QQ(24)
278
True
279
"""
280
pass
281
282
283
def rGRCtests():
284
"""
285
Test the surjectivity of the _to_bic maps.
286
287
EXAMPLES::
288
289
sage: from admcycles.diffstrata import *
290
sage: X=GeneralisedStratum([Signature((2,2,-2))])
291
sage: assert all(set(X.DG.top_to_bic(i).keys()) == set(range(len(X.bics[i].level(0).bics))) for i in range(len(X.bics)))
292
sage: assert all(set(X.DG.bot_to_bic(i).keys()) == set(range(len(X.bics[i].level(1).bics))) for i in range(len(X.bics)))
293
"""
294
pass
295
296
297
def middle_level_degeneration(sig):
298
"""
299
Check if gluing in middle bics gives (at least as a set) all length three profiles.
300
301
Maybe think of some more sophisticated test...
302
303
Args:
304
sig (tuple): Signature tuple.
305
306
EXAMPLES::
307
308
sage: from admcycles.diffstrata.tests import middle_level_degeneration
309
sage: middle_level_degeneration((1,1))
310
sage: middle_level_degeneration((2,2,-2))
311
sage: middle_level_degeneration((4,))
312
sage: middle_level_degeneration((2,2,2,-6))
313
"""
314
X = GeneralisedStratum([Signature(sig)])
315
three_level_graphs = X.enhanced_profiles_of_length(2)
316
four_level_profiles_set = set(X.lookup_list[3])
317
seen = set()
318
for ep in three_level_graphs:
319
p, _i = ep
320
for b in X.DG.middle_to_bic(ep).values():
321
seen.add((p[0], b, p[1]))
322
assert seen == four_level_profiles_set
323
324
325
def leg_test(sig, quiet=False):
326
"""
327
Tests on each dimension 1 graphs of the stratum with signature sig:
328
We test on each one-dimensional level if the evaluation of the xi glued in at
329
that level is the same (for every leg!) as the product of the graph with xi on
330
the whole stratum.
331
332
Args:
333
sig (tuple): Signature of a stratum.
334
quiet (bool, optional): No output. Defaults to False.
335
336
EXAMPLES::
337
338
sage: from admcycles.diffstrata.tests import leg_test
339
sage: leg_test((6,1,-7),quiet=True)
340
sage: leg_test((3,-1,-2),quiet=True)
341
sage: leg_test((1,1),quiet=True)
342
sage: leg_test((2,2,-2),quiet=True) # long time
343
"""
344
X = GeneralisedStratum([Signature(sig)])
345
d = X.dim() - 1 # codim
346
for p in X.lookup_list[d]:
347
components = X.lookup(p)
348
for i, B in enumerate(components):
349
enh_profile = (p, i)
350
global_xi_prod = (X.xi_with_leg(quiet=True) *
351
X.taut_from_graph(p, i)).evaluate(quiet=True)
352
top_dim = X.lookup_graph(*enh_profile).level(0).dim()
353
if not quiet:
354
print("Graph %r: xi evaluated: %r (dim of Level 0: %r)" %
355
(enh_profile, global_xi_prod, top_dim))
356
if top_dim == 0:
357
assert global_xi_prod == 0
358
for l in range(d):
359
L = B.level(l)
360
if L.dim() != 1:
361
continue
362
first = None
363
for leg in L.leg_dict:
364
level_xi_prod = X.xi_at_level(
365
l, (p, i), leg=leg, quiet=True).evaluate(quiet=True)
366
if not first:
367
first = level_xi_prod
368
if not quiet:
369
print("level: %r, leg: %r, xi ev: %r" %
370
(l, leg, level_xi_prod))
371
if quiet:
372
assert first == level_xi_prod
373
if l == 0:
374
assert global_xi_prod == level_xi_prod
375
376
377
def stratumclasstests():
378
"""
379
Tests of stratum class calculations.
380
381
EXAMPLES::
382
383
sage: from admcycles.diffstrata import *
384
385
sage: X=GeneralisedStratum([Signature((23,5,-13,-17))])
386
sage: assert X.res_stratum_class([(0,2)]).evaluate(quiet=True) == 5
387
"""
388
pass
389
390
391
def commutativity_check(sig):
392
"""
393
Run a (large) commutativity check on Stratum(sig)
394
to check the normal bundle.
395
396
More precisely, we check all top-degree products
397
of BICs in this stratum, multiplying them from
398
right-to-left and from left-to-right and checking
399
that the evaluations agree.
400
401
Args:
402
sig (tuple): signature tuple
403
404
Raises:
405
RuntimeError: raised if a commutator doesn't
406
evaluate to 0.
407
"""
408
X = GeneralisedStratum([Signature(sig)])
409
n = X.dim()
410
for T in product(range(len(X.bics)), repeat=n):
411
print("Starting IPs")
412
print(T)
413
PR = X.taut_from_graph((T[0],))
414
RP = X.taut_from_graph((T[-1],))
415
for i in range(1, n):
416
PR *= X.taut_from_graph((T[i],))
417
RP *= X.taut_from_graph((T[-1 - i],))
418
print(T[0], T[1])
419
RP = RP.evaluate(quiet=True)
420
PR = PR.evaluate(quiet=True)
421
if PR - RP != 0:
422
print(T, " gives ", PR - RP)
423
raise RuntimeError
424
425
426
def c2_banana_tests(k):
427
"""
428
Check c2 evaluation for the bananas.
429
430
Args:
431
k (int): zero of the banana
432
433
Returns:
434
RationalNumber: difference of evaluate of c2 and c2
435
formula in terms of c1 and ch2 (should be 0!!!)
436
437
EXAMPLES::
438
439
sage: from admcycles.diffstrata.tests import c2_banana_tests
440
sage: for k in range(1,10): assert c2_banana_tests(k) == 0
441
"""
442
X = GeneralisedStratum([Signature((-k - 1, k, 1))])
443
assert (X.c2_E).evaluate(quiet=True) == QQ(k * (k + 1)) / QQ(6)
444
return (X.c2_E).evaluate(quiet=True) - QQ(1) / QQ(2) * \
445
(X.c1_E**2 + (-2) * X.ch2_E).evaluate(quiet=True)
446
447
448
def c2_test(sig):
449
"""
450
Compare c2_E to (ch_1^2 - 2ch_2)/2.
451
452
EXAMPLES::
453
454
sage: from admcycles.diffstrata.tests import c2_test
455
sage: assert c2_test((1,1,1,1,-6)) == 2
456
sage: assert c2_test((-2,-2,-2,-2,6)) == 2
457
"""
458
X = GeneralisedStratum([Signature(sig)])
459
c2ev = (X.c2_E).evaluate(quiet=True)
460
diff = c2ev - QQ(1) / QQ(2) * (X.c1_E**2 + (-2) * X.ch2_E).evaluate(quiet=True)
461
assert diff == 0
462
return c2ev
463
464
465
def c1_test(k):
466
"""
467
Check the Euler characteristic of (k,-k) (modular curves).
468
469
EXAMPLES::
470
471
sage: from admcycles.diffstrata.tests import c1_test
472
sage: for k in range(2,20): assert c1_test(k)
473
"""
474
X = GeneralisedStratum([Signature((k, -k))])
475
return (X.c1_E).evaluate(quiet=True) == QQ(k * k - 1) / QQ(12)
476
477
478
def ch1_pow_test(sig_tuple, deg=3):
479
"""
480
Compare ch1_pow(deg) to c1^deg in Stratum(sig_tuple).
481
482
We multiply with classes to obtain top-degree and then
483
evaluate.
484
485
This should produce a series of 0s.
486
487
Args:
488
sig_tuple (tuple): signature tuple
489
deg (int, optional): degree. Defaults to 3.
490
491
EXAMPLES::
492
493
sage: from admcycles.diffstrata.tests import ch1_pow_test
494
sage: ch1_pow_test((1,1), 2)
495
Calculating difference...
496
Products of BICs:
497
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
498
Products with graphs of codim 2:
499
0 0 0 0
500
"""
501
X = GeneralisedStratum([Signature(sig_tuple)])
502
codim = X.dim() - deg
503
print('Calculating difference...')
504
c = X.chern_poly(upto=1)
505
diff = c[1]**deg - X.ch1_pow(deg)
506
if codim == 0:
507
print(diff.evaluate(quiet=True))
508
return
509
print('Products of BICs:')
510
for pr in product(range(len(X.bics)), repeat=codim):
511
expr = diff
512
for b in pr:
513
expr *= X.taut_from_graph((b,))
514
ev = expr.evaluate(quiet=True)
515
print(ev, end=' ')
516
sys.stdout.flush()
517
print()
518
if codim > 1:
519
print('Products with graphs of codim %r:' % codim)
520
for ep in X.enhanced_profiles_of_length(codim):
521
print((diff * X.taut_from_graph(*ep)).evaluate(quiet=True), end=' ')
522
sys.stdout.flush()
523
print()
524
525
526
def chern_poly_test(sig):
527
"""
528
Compare chern_poly and chern_class.
529
530
We multiply with classes to obtain top-degree and then
531
evaluate.
532
533
Args:
534
sig (tuple): signature tuple
535
536
Returns:
537
bool: True
538
539
EXAMPLES::
540
541
sage: from admcycles.diffstrata.tests import chern_poly_test
542
sage: chern_poly_test((2,)) # doctest:+ELLIPSIS
543
Calculating Chern Polynomial via character...
544
Calculating difference...
545
Comparing top classes: 0
546
Comparing Products of 1 BICs and psi classes:
547
BIC 0 0 BIC 1 0 Psi 1 0
548
Comparing Products of 2 BICs and psi classes:
549
BIC 0 BIC 0 0 BIC 0 BIC 1 0 BIC 0 Psi 1 0 BIC 1 BIC 0 0 BIC 1 BIC 1 0 BIC 1 Psi 1 0 Psi 1 BIC 0 0 Psi 1 BIC 1 0 Psi 1 Psi 1 0
550
Products with graphs of codim 2:
551
Profile (..., 0) 0
552
All tests passed: True
553
True
554
"""
555
X = GeneralisedStratum([Signature(sig)])
556
print('Calculating Chern Polynomial via character...')
557
c = X.chern_poly()
558
print('Calculating difference...')
559
diff = [c[i] - X.chern_class(i) for i in reversed(range(1, X.dim() + 1))]
560
evs = []
561
for codim in range(X.dim()):
562
assert diff[codim].is_equidimensional()
563
if diff[codim].psi_list:
564
assert diff[codim].psi_list[0][1].degree == X.dim() - codim
565
if codim == 0:
566
print("Comparing top classes:", end=' ')
567
sys.stdout.flush()
568
ev = diff[codim].evaluate(quiet=True)
569
print(ev)
570
evs.append(ev)
571
continue
572
print('Comparing Products of %r BICs and psi classes:' % codim)
573
for pr in product(range(len(X.bics) + len(sig)), repeat=codim):
574
expr = diff[codim]
575
for b in pr:
576
if b < len(X.bics):
577
print('BIC %r' % b, end=' ')
578
expr *= X.taut_from_graph((b,))
579
else:
580
psi_num = b - len(X.bics) + 1
581
print('Psi %r' % psi_num, end=' ')
582
expr *= X.psi(psi_num)
583
ev = expr.evaluate(quiet=True)
584
print(ev, end=' ')
585
evs.append(ev)
586
sys.stdout.flush()
587
print()
588
if codim > 1:
589
print('Products with graphs of codim %r:' % codim)
590
for ep in X.enhanced_profiles_of_length(codim):
591
print('Profile %r' % (ep,), end=' ')
592
ev = (diff[codim] * X.taut_from_graph(*ep)).evaluate(quiet=True)
593
print(ev, end=' ')
594
sys.stdout.flush()
595
evs.append(ev)
596
print()
597
passed = all(ev == 0 for ev in evs)
598
print('All tests passed:', passed)
599
return passed
600
601
602
def chern_poly_tests(sig_list):
603
"""
604
Apply chern_poly_test to a list of signatures.
605
606
Args:
607
sig_list (iterable): list of signature tuples.
608
609
EXAMPLES::
610
611
sage: from admcycles.diffstrata.tests import chern_poly_tests
612
sage: chern_poly_tests([(0,),(2,-2)])
613
Entering Stratum (0,)
614
Calculating Chern Polynomial via character...
615
Calculating difference...
616
Comparing top classes: 0
617
All tests passed: True
618
Done.
619
Entering Stratum (2, -2)
620
Calculating Chern Polynomial via character...
621
Calculating difference...
622
Comparing top classes: 0
623
All tests passed: True
624
Done.
625
All strata tests passed: True
626
"""
627
check_vec = []
628
for sig in sig_list:
629
print('Entering Stratum', sig)
630
check_vec.append(chern_poly_test(sig))
631
print('Done.')
632
print('All strata tests passed:', all(check_vec))
633
634
635
class C3_coefficient_hunter:
636
"""
637
A class that illustrates how to use symbolic variables to
638
test coefficients in explicit formulas of c_k.
639
"""
640
641
def __init__(self, sig=None, fct=None):
642
self.NUM_VARS = 33
643
self.DEG = 3
644
if fct is None:
645
self.fct = 'c3_E'
646
else:
647
self.fct = fct
648
self.t = t = SR.var('t', self.NUM_VARS)
649
self.var_list = list(t)
650
self.M = None
651
self.constants = []
652
if not (sig is None):
653
self.add_stratum(sig)
654
655
def add_stratum(self, sig):
656
X = GeneralisedStratum([Signature(sig)])
657
print('Calculating difference...')
658
expr = getattr(X, self.fct)() - X.chern_poly(upto=self.DEG)[self.DEG]
659
codim = X.dim() - self.DEG
660
if codim == 0:
661
self._add_eq(expr.evaluate(quiet=True))
662
return
663
print('Products of BICs and Psis:')
664
for pr in product(range(len(X.bics) + len(sig)), repeat=codim):
665
diff = expr
666
for b in pr:
667
if b < len(X.bics):
668
print('BIC %r' % b, end=' ')
669
diff *= X.taut_from_graph((b,))
670
else:
671
psi_num = b - len(X.bics) + 1
672
print('Psi %r' % psi_num, end=' ')
673
diff *= X.psi(psi_num)
674
ev = diff.evaluate(quiet=True)
675
self._add_eq(ev)
676
if codim > 1:
677
print('Products with graphs of codim %r:' % codim)
678
for ep in X.enhanced_profiles_of_length(codim):
679
print('Profile %r' % (ep,), end=' ')
680
self._add_eq(
681
(expr * X.taut_from_graph(*ep)).evaluate(quiet=True))
682
683
def _add_eq(self, expr):
684
print("Adding equation: %r" % expr)
685
if expr == 0:
686
return
687
eqn = [expr.coefficient(v) for v in self.var_list]
688
cst = expr.substitute({v: 0 for v in expr.free_variables()})
689
if self.M is None:
690
self.M = Matrix(QQ, [eqn])
691
else:
692
self.M = self.M.stack(Matrix(QQ, [eqn]))
693
self.constants.append(cst)
694
695
def solve(self):
696
self.solution = self.M.solve_right(
697
free_module_element(QQ, self.constants))
698
699
def __str__(self):
700
s = ["Coefficient Matrix:\n"]
701
s.append(str(self.M))
702
s.append('\nRank: %r' % self.M.rank())
703
s.append("\nConstants:\n")
704
s.append(str(self.constants))
705
self.solve()
706
s.append('\nSolution:\n')
707
s.append(str(self.solution))
708
return ''.join(s)
709
710
711
class IntersectionMatrix:
712
"""
713
The intersection matrix of a stratum.
714
"""
715
716
def __init__(self, sig):
717
"""
718
Initialise stratum and cache.
719
720
Args:
721
sig (tuple): signature tuple
722
"""
723
self.X = Stratum(sig)
724
self.info_vecs = {}
725
self.codim_one_summary()
726
727
@cached_method
728
def codim_xis(self, k):
729
"""
730
Classes of codimension k, that graphs with <= k levels
731
with xi powers on levels to reach deg k.
732
733
Args:
734
k (int): degree
735
736
Returns:
737
list: list of ELGTautClasses of deg k
738
"""
739
print('Calculating classes of codim %r...' % k, end=' ')
740
sys.stdout.flush()
741
classes = []
742
info_vec = []
743
for l in range(k + 1):
744
xi_deg = k - l
745
for ep in self.X.enhanced_profiles_of_length(l):
746
AG = self.X.additive_generator(ep)
747
# distribute xi powers:
748
if xi_deg == 0:
749
# no xis to distribute
750
classes.append(AG.as_taut())
751
info_vec.append((ep, {}))
752
continue
753
level_dims = [AG.level_dim(l) for l in range(AG.codim + 1)]
754
# we number the positive-dimensional levels:
755
pos_dim_level_dict = {}
756
i = 0
757
for l, dim in enumerate(level_dims):
758
if dim > 0:
759
pos_dim_level_dict[i] = l
760
i += 1
761
# not the most efficient way, but good enough for now:
762
for exponents in WeightedIntegerVectors(
763
xi_deg, [1] * len(pos_dim_level_dict)):
764
if any(exponents[i] > level_dims[pos_dim_level_dict[i]]
765
for i in range(len(pos_dim_level_dict))):
766
continue
767
prod = AG.as_taut()
768
for i, e in enumerate(exponents):
769
curr_xi = self.X.xi_at_level_pow(
770
pos_dim_level_dict[i], ep, e)
771
prod = self.X.intersection(prod, curr_xi, ep)
772
classes.append(prod)
773
info_vec.append(
774
(ep, {l: exponents[i] for i, l in pos_dim_level_dict.items()}))
775
print('%r found' % len(classes))
776
self.info_vecs[k] = info_vec
777
return classes
778
779
@cached_method
780
def int_matrix(self, k=1):
781
"""
782
Matrix of evaluations of top-degree classes (products of codim_xis(k)
783
and codim_xis(dim-k)).
784
785
Args:
786
k (int, optional): degree. Defaults to 1.
787
788
Returns:
789
list: list of lists of rational numbers.
790
"""
791
x_classes = self.codim_xis(k)
792
y_classes = self.codim_xis(self.X.dim() - k)
793
M = [[self.X.ZERO for _ in range(len(y_classes))]
794
for _ in range(len(x_classes))]
795
print('Calculating intersection matrix for codim %r...' % k, end=' ')
796
sys.stdout.flush()
797
for i, x in enumerate(x_classes):
798
for j, y in enumerate(y_classes):
799
prod = x * y
800
assert prod.is_equidimensional()
801
assert prod == self.X.ZERO or prod.psi_list[0][1].degree == self.X.dim(
802
)
803
M[i][j] = (prod).evaluate()
804
print('Done!')
805
return M
806
807
def codim_one_summary(self):
808
"""
809
Display codim 1 matrix summary.
810
"""
811
print(self.X)
812
M = self.int_matrix(1)
813
rk = Matrix(M).rank()
814
print('Codim 1: Rank of %r x %r matrix: %r' % (len(M), len(M[0]), rk))
815
816
def summary(self):
817
"""
818
Summary of matrices in all codimensions.
819
"""
820
print(self.X)
821
for k in range(self.X.dim() + 1):
822
M = self.int_matrix(k)
823
rk = Matrix(M).rank()
824
print('Codim %r: Rank of %r x %r matrix: %r' %
825
(k, len(M), len(M[0]), rk))
826
827
def print_matrix(self, k=1):
828
"""
829
Human readable output of int_matrix(k) values.
830
831
Args:
832
k (int, optional): degree. Defaults to 1.
833
"""
834
for row in range(len(self.int_matrix(k))):
835
self.print_row(row + 1, k)
836
837
def info(self, i, k=1):
838
"""
839
A string representation of the i-th codim k class.
840
841
Args:
842
i (int): index of codim_xis(k)
843
k (int, optional): degree. Defaults to 1.
844
845
Returns:
846
String: string description of which levels carry xis.
847
"""
848
if k not in self.info_vecs:
849
self.codim_xis(k)
850
ep, d = self.info_vecs[k][i]
851
s = str(ep)
852
for l, e in d.items():
853
s += ' level %r: xi^%r,' % (l, e)
854
return s
855
856
def entry(self, row, col, k=1):
857
"""
858
Human-readable representation of the entry row, col of int_matrix(k).
859
860
Note that this prints the classes being multiplied, not the values.
861
862
Args:
863
row (int): row index (math notation, i.e. starting at 1)
864
col (int): col index (math notation, i.e. starting at 1)
865
k (int, optional): degree. Defaults to 1.
866
867
Returns:
868
String: info of the two factors at this entry
869
"""
870
# math notation, i.e. starting at 1!!
871
return self.info(row - 1, k) + ' * ' + self.info(col - 1, self.X.dim() - k)
872
873
def print_row(self, row, k=1):
874
"""
875
Human-readable output of the row of int_matrix(k)
876
877
Args:
878
row (int): row (math notation, i.e. starting at 1)
879
k (int, optional): degree. Defaults to 1.
880
"""
881
# use math notation, i.e. starting at 1!!
882
M = self.int_matrix(k)
883
print("Row %r" % row)
884
for col, value in enumerate(M[row - 1]):
885
print('Col %r: %s value: %r' %
886
(col + 1, self.entry(row, col + 1, k), value))
887
888
def print_col(self, col, k=1):
889
"""
890
Human-readable output of the col of int_matrix(k)
891
892
Args:
893
col (int): column (math notation, i.e. starting at 1)
894
k (int, optional): degree. Defaults to 1.
895
"""
896
# use math notation, i.e. starting at 1!!
897
M = self.int_matrix(k)
898
print("Col %r" % col)
899
for row in range(len(M)):
900
print('Row %r: %s value: %r' %
901
(row + 1, self.entry(row + 1, col, k), M[row][col - 1]))
902
903
#########################################
904
905
906
def push_pull(sig, T_name=None):
907
print('Testing non-horizontal push-pull for stratum %r' % (sig,), end=' ')
908
sys.stdout.flush()
909
X = Stratum(sig)
910
if T_name == 'xi':
911
print('using xi:')
912
T = X.xi
913
else:
914
T = X.ONE
915
print('using [1]:')
916
g = X._g[0]
917
n = X._n
918
for G in admcycles.admcycles.list_strata(g, n, 1):
919
if len(G.genera()) == 1:
920
# horizontal
921
continue
922
print("%r: " % G, end='')
923
sys.stdout.flush()
924
pullback = X.boundary_pullback(G)
925
if pullback == X.ZERO:
926
print('ZERO')
927
else:
928
LHS = (T * pullback).to_prodtautclass().pushforward()
929
RHS = admcycles.admcycles.tautclass(
930
[admcycles.admcycles.decstratum(G)]) * T.to_prodtautclass().pushforward()
931
print((LHS - RHS).is_zero())
932
933