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