unlisted
ubuntu2004import sys12from itertools import product34from sage.rings.rational_field import QQ # pylint: disable=import-error5from sage.arith.functions import lcm # pylint: disable=import-error6from sage.arith.misc import gcd # pylint: disable=import-error7from sage.symbolic.ring import SR # pylint: disable=import-error8from sage.matrix.constructor import Matrix # pylint: disable=import-error9from sage.modules.free_module_element import free_module_element # pylint: disable=import-error10from sage.combinat.integer_vector_weighted import WeightedIntegerVectors # pylint: disable=import-error11from sage.misc.cachefunc import cached_method # pylint: disable=import-error1213from admcycles.diffstrata.generalisedstratum import GeneralisedStratum, Stratum14from admcycles.diffstrata.sig import Signature1516import admcycles.admcycles171819def test_calL(sig):20"""21Compare calL and the 'error term' of cnb.2223EXAMPLES::2425sage: from admcycles.diffstrata.tests import test_calL26sage: test_calL((1,1,1,1,-6))27sage: test_calL((4,))28"""29X = GeneralisedStratum([Signature(sig)])30for i, B in enumerate(X.bics):31ll = lcm(B.LG.prongs.values())32assert X.calL(((i,), 0), 0) + ll * X.cnb(((i,), 0), ((i,), 0)) + X.gen_pullback_taut(X.xi_at_level(0, ((i,), 0)),33((i,), 0), ((i,), 0)) + (-1) * X.gen_pullback_taut(X.xi_at_level(1, ((i,), 0)), ((i,), 0), ((i,), 0)) == X.ZERO343536def meromorphic_tests():37"""38EXAMPLES::3940sage: from admcycles.diffstrata import *41sage: X=GeneralisedStratum([Signature((1,1,1,1,-6))])42sage: (X.xi^2).evaluate(quiet=True)43254445sage: X=GeneralisedStratum([Signature((-2,-2,-2,-2,6))])46sage: (X.xi^X.dim()).evaluate(quiet=True)47304849Testing normal bundles:5051sage: X=GeneralisedStratum([Signature((2,2,-2))])52sage: td0 = X.taut_from_graph((0,))53sage: td1 = X.taut_from_graph((1,))54sage: td4 = X.taut_from_graph((4,))55sage: td5 = X.taut_from_graph((5,))56sage: td8 = X.taut_from_graph((8,))57sage: assert X.ZERO == td0^2*td1 - td0*td1*td0 # not 'safe' # doctest:+SKIP58sage: assert X.ZERO == td0^2*td5 - td0*td5*td0 # not 'safe' # doctest:+SKIP59sage: assert X.ZERO == td0^2*td8 - td0*td8*td0 # not 'safe' # doctest:+SKIP60sage: assert (td8^3*td4).evaluate(quiet=True) == (td8^2*td4*td8).evaluate(quiet=True) == (td8*td4*td8^2).evaluate(quiet=True)6162"""63pass646566def gengenustwotests():67"""68EXAMPLES::6970sage: from admcycles.diffstrata import *71sage: X=GeneralisedStratum([Signature((2,))])72sage: assert (X.xi^X.dim()).evaluate(quiet=True) == -1/64073sage: ct=[i for i, B in enumerate(X.bics) if len(B.LG.edges) == 1]74sage: ct_index = ct[0] # compact type graph75sage: ct_taut = X.taut_from_graph((ct_index,))76sage: assert (X.c2_E*ct_taut).evaluate(quiet=True) == 1/4877sage: banana_index = 1 - ct_index # only 2 BICs!78sage: banana_taut = X.taut_from_graph((banana_index,))79sage: assert (X.c2_E*banana_taut).evaluate(quiet=True) == 1/2480sage: assert (X.c1_E*banana_taut**2).evaluate(quiet=True) == -1/1681sage: assert (X.c1_E*banana_taut*ct_taut).evaluate(quiet=True) == 1/2482sage: assert (X.c1_E*ct_taut**2).evaluate(quiet=True) == -1/4883sage: assert (ct_taut**3).evaluate(quiet=True) == 1/9684sage: assert (banana_taut**3).evaluate(quiet=True) == 1/4885sage: assert (ct_taut*banana_taut**2).evaluate(quiet=True) == 086sage: assert (ct_taut*ct_taut*banana_taut).evaluate(quiet=True) == -1/488788sage: X=GeneralisedStratum([Signature((1,1))])89sage: at1 = X.taut_from_graph((1,))90sage: at2 = X.taut_from_graph((2,))91sage: X.ZERO == at1^2*at2 + (-1)*at1*at2*at192True93sage: X.ZERO == (-1)*(at1+at2)^3*at2 + at1^3*at2 + 3*at1^2*at2*at2 + 3*at1*at2^2*at2 + at2^3*at294True95sage: X.ZERO == (-1)*(at1+at2)^4 + at1^4 + 4*at1^3*at2 + 6*at1^2*at2^2 + 4*at1^1*at2^3 + at2^496True97sage: (X.xi^X.dim()).evaluate(quiet=True)98099sage: psi1 = AdditiveGenerator(X,((),0),{1:1}).as_taut()100sage: (X.xi^3*psi1).evaluate(quiet=True)101-1/360102"""103pass104105106def genusthreetests():107"""108Testing Normal bundles in min stratum (4):109110EXAMPLES::111112sage: from admcycles.diffstrata import *113sage: X=GeneralisedStratum([Signature((4,))])114115sage: v_banana = [i for i, B in enumerate(X.bics) if B.LG.genera == [1,1,0]]116sage: v_banana_taut=X.taut_from_graph((v_banana[0],))117sage: g1_banana = [i for i, B in enumerate(X.bics) if B.LG.genera == [1,1]]118sage: g1_banana_taut=X.taut_from_graph((g1_banana[0],))119120sage: assert g1_banana_taut**2*v_banana_taut + (-1)*g1_banana_taut*v_banana_taut*g1_banana_taut == X.ZERO121sage: assert v_banana_taut**2*g1_banana_taut + (-1)*v_banana_taut*g1_banana_taut*v_banana_taut == X.ZERO122123sage: (X.xi_with_leg(quiet=True)^X.dim()).evaluate(quiet=True) # long time # optional - local124305/580608125"""126pass127128129def genusfourtests():130"""131Tests in H(6): (think of smart NB test...)132133EXAMPLES::134135sage: from admcycles.diffstrata import *136137"""138pass139140141class BananaSuite:142"""143A frontend for the Stratum (k, 1, -k-1).144145This class models the situation of sec 10.2 of CMZ20146with a method D for accessing the divisors in the147notation of loc. cit. (either D(i), i=2,3,4 or D(i,a)148for i=1,5).149"""150151def __init__(self, k):152"""153Initialise the genus 1 stratum (k, 1, -k-1).154155Args:156k (int): order of zero157"""158self._k = k159self._X = GeneralisedStratum([Signature((k, 1, -k - 1))])160161def D(self, i, a=1):162"""163The divisor using the notation of Sec. 10.2.164165Args:166i (int): index 1,2,3,4,5167a (int, optional): prong for i=1 or 5. Defaults to 1.168169Returns:170ELGTautClass: Tautological class of the divisor D_{i,a}.171"""172if i == 1:173for b, B in enumerate(self._X.bics):174v = B.LG.verticesonlevel(0)[0]175if (B.LG.genus(v) == 0 and176len(B.LG.ordersonvertex(v)) == 3 and177len(B.LG.edges) == 2 and178a in B.LG.prongs.values()):179assert -self._k - 1 in B.LG.ordersonvertex(v),\180"%r" % B181return self._X.taut_from_graph((b,))182elif i == 2:183for b, B in enumerate(self._X.bics):184v = B.LG.verticesonlevel(0)[0]185if (B.LG.genus(v) == 1 and len(B.LG.ordersonvertex(v)) == 2):186assert -self._k - 1 in B.LG.ordersonvertex(v),\187"%r" % B188return self._X.taut_from_graph((b,))189elif i == 3:190for b, B in enumerate(self._X.bics):191v = B.LG.verticesonlevel(0)[0]192if (B.LG.genus(v) == 1 and len(B.LG.ordersonvertex(v)) == 1):193return self._X.taut_from_graph((b,))194elif i == 4:195for b, B in enumerate(self._X.bics):196v = B.LG.verticesonlevel(-1)[0]197if (B.LG.genus(v) == 1 and len(B.LG.ordersonvertex(v)) == 2):198return self._X.taut_from_graph((b,))199elif i == 5:200for b, B in enumerate(self._X.bics):201v = B.LG.verticesonlevel(0)[0]202if (B.LG.genus(v) == 0 and203len(B.LG.ordersonvertex(v)) == 4 and204len(B.LG.edges) == 2 and205a in B.LG.prongs.values()):206assert -self._k - 1 in B.LG.ordersonvertex(v),\207"%r" % B208return self._X.taut_from_graph((b,))209else:210return None211212def check(self, quiet=False):213"""214Check Prop 10.1215216Args:217quiet (bool, optional): No output. Defaults to False.218219Returns:220bool: Should always return True.221"""222check_list = []223224def delta(k, a):225if a == k / 2:226return QQ(1) / QQ(2)227else:228return 1229for a in range(1, self._k + 1):230si = (self.D(1, a)**2).evaluate(quiet=True)231rhs = -QQ(delta(self._k + 1, a) * self._k *232gcd(a, self._k + 1 - a)) / QQ(lcm(a, self._k + 1 - a))233check_list.append(si == rhs)234if not quiet:235print("D(1,%r)^2 = %r, RHS = %r" % (a, si, rhs))236for a in range(1, self._k):237si = (self.D(5, a)**2).evaluate(quiet=True)238rhs = -QQ(delta(self._k, a) * (self._k + 1) *239gcd(a, self._k - a)) / QQ(lcm(a, self._k - a))240check_list.append(si == rhs)241if not quiet:242print("D(5,%r)^2 = %r, RHS = %r" % (a, si, rhs))243return all(check_list)244245def banana_tests(self):246"""247EXAMPLES::248249sage: from admcycles.diffstrata.tests import BananaSuite250sage: B=BananaSuite(2)251sage: B.check(quiet=True)252True253sage: (B._X.xi**2).evaluate(quiet=True) == QQ(2**4 - 1)/QQ(24)254True255sage: assert((B._X.xi_with_leg(quiet=True)*B.D(5,1)).evaluate(quiet=True) == \256B._X.xi_at_level(0,B.D(5,1).psi_list[0][1].enh_profile,quiet=True).evaluate(quiet=True) == -1)257sage: 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)258259sage: B=BananaSuite(5)260sage: B.check(quiet=True)261True262sage: B=BananaSuite(5)263sage: (B._X.xi**2).evaluate(quiet=True) == QQ(5**4 - 1)/QQ(24)264True265266sage: B=BananaSuite(6)267sage: assert((B._X.xi_with_leg(quiet=True)*B.D(5,2)).evaluate(quiet=True) == \268B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=1,quiet=True).evaluate(quiet=True) == \269B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=2,quiet=True).evaluate(quiet=True) == \270B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=3,quiet=True).evaluate(quiet=True) == \271B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=4,quiet=True).evaluate(quiet=True) == -12)272273sage: B=BananaSuite(10)274sage: B.check(quiet=True)275True276sage: (B._X.xi**2).evaluate(quiet=True) == QQ(10**4 - 1)/QQ(24)277True278"""279pass280281282def rGRCtests():283"""284Test the surjectivity of the _to_bic maps.285286EXAMPLES::287288sage: from admcycles.diffstrata import *289sage: X=GeneralisedStratum([Signature((2,2,-2))])290sage: 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)))291sage: 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)))292"""293pass294295296def middle_level_degeneration(sig):297"""298Check if gluing in middle bics gives (at least as a set) all length three profiles.299300Maybe think of some more sophisticated test...301302Args:303sig (tuple): Signature tuple.304305EXAMPLES::306307sage: from admcycles.diffstrata.tests import middle_level_degeneration308sage: middle_level_degeneration((1,1))309sage: middle_level_degeneration((2,2,-2))310sage: middle_level_degeneration((4,))311sage: middle_level_degeneration((2,2,2,-6))312"""313X = GeneralisedStratum([Signature(sig)])314three_level_graphs = X.enhanced_profiles_of_length(2)315four_level_profiles_set = set(X.lookup_list[3])316seen = set()317for ep in three_level_graphs:318p, _i = ep319for b in X.DG.middle_to_bic(ep).values():320seen.add((p[0], b, p[1]))321assert seen == four_level_profiles_set322323324def leg_test(sig, quiet=False):325"""326Tests on each dimension 1 graphs of the stratum with signature sig:327We test on each one-dimensional level if the evaluation of the xi glued in at328that level is the same (for every leg!) as the product of the graph with xi on329the whole stratum.330331Args:332sig (tuple): Signature of a stratum.333quiet (bool, optional): No output. Defaults to False.334335EXAMPLES::336337sage: from admcycles.diffstrata.tests import leg_test338sage: leg_test((6,1,-7),quiet=True)339sage: leg_test((3,-1,-2),quiet=True)340sage: leg_test((1,1),quiet=True)341sage: leg_test((2,2,-2),quiet=True) # long time342"""343X = GeneralisedStratum([Signature(sig)])344d = X.dim() - 1 # codim345for p in X.lookup_list[d]:346components = X.lookup(p)347for i, B in enumerate(components):348enh_profile = (p, i)349global_xi_prod = (X.xi_with_leg(quiet=True) *350X.taut_from_graph(p, i)).evaluate(quiet=True)351top_dim = X.lookup_graph(*enh_profile).level(0).dim()352if not quiet:353print("Graph %r: xi evaluated: %r (dim of Level 0: %r)" %354(enh_profile, global_xi_prod, top_dim))355if top_dim == 0:356assert global_xi_prod == 0357for l in range(d):358L = B.level(l)359if L.dim() != 1:360continue361first = None362for leg in L.leg_dict:363level_xi_prod = X.xi_at_level(364l, (p, i), leg=leg, quiet=True).evaluate(quiet=True)365if not first:366first = level_xi_prod367if not quiet:368print("level: %r, leg: %r, xi ev: %r" %369(l, leg, level_xi_prod))370if quiet:371assert first == level_xi_prod372if l == 0:373assert global_xi_prod == level_xi_prod374375376def stratumclasstests():377"""378Tests of stratum class calculations.379380EXAMPLES::381382sage: from admcycles.diffstrata import *383384sage: X=GeneralisedStratum([Signature((23,5,-13,-17))])385sage: assert X.res_stratum_class([(0,2)]).evaluate(quiet=True) == 5386"""387pass388389390def commutativity_check(sig):391"""392Run a (large) commutativity check on Stratum(sig)393to check the normal bundle.394395More precisely, we check all top-degree products396of BICs in this stratum, multiplying them from397right-to-left and from left-to-right and checking398that the evaluations agree.399400Args:401sig (tuple): signature tuple402403Raises:404RuntimeError: raised if a commutator doesn't405evaluate to 0.406"""407X = GeneralisedStratum([Signature(sig)])408n = X.dim()409for T in product(range(len(X.bics)), repeat=n):410print("Starting IPs")411print(T)412PR = X.taut_from_graph((T[0],))413RP = X.taut_from_graph((T[-1],))414for i in range(1, n):415PR *= X.taut_from_graph((T[i],))416RP *= X.taut_from_graph((T[-1 - i],))417print(T[0], T[1])418RP = RP.evaluate(quiet=True)419PR = PR.evaluate(quiet=True)420if PR - RP != 0:421print(T, " gives ", PR - RP)422raise RuntimeError423424425def c2_banana_tests(k):426"""427Check c2 evaluation for the bananas.428429Args:430k (int): zero of the banana431432Returns:433RationalNumber: difference of evaluate of c2 and c2434formula in terms of c1 and ch2 (should be 0!!!)435436EXAMPLES::437438sage: from admcycles.diffstrata.tests import c2_banana_tests439sage: for k in range(1,10): assert c2_banana_tests(k) == 0440"""441X = GeneralisedStratum([Signature((-k - 1, k, 1))])442assert (X.c2_E).evaluate(quiet=True) == QQ(k * (k + 1)) / QQ(6)443return (X.c2_E).evaluate(quiet=True) - QQ(1) / QQ(2) * \444(X.c1_E**2 + (-2) * X.ch2_E).evaluate(quiet=True)445446447def c2_test(sig):448"""449Compare c2_E to (ch_1^2 - 2ch_2)/2.450451EXAMPLES::452453sage: from admcycles.diffstrata.tests import c2_test454sage: assert c2_test((1,1,1,1,-6)) == 2455sage: assert c2_test((-2,-2,-2,-2,6)) == 2456"""457X = GeneralisedStratum([Signature(sig)])458c2ev = (X.c2_E).evaluate(quiet=True)459diff = c2ev - QQ(1) / QQ(2) * (X.c1_E**2 + (-2) * X.ch2_E).evaluate(quiet=True)460assert diff == 0461return c2ev462463464def c1_test(k):465"""466Check the Euler characteristic of (k,-k) (modular curves).467468EXAMPLES::469470sage: from admcycles.diffstrata.tests import c1_test471sage: for k in range(2,20): assert c1_test(k)472"""473X = GeneralisedStratum([Signature((k, -k))])474return (X.c1_E).evaluate(quiet=True) == QQ(k * k - 1) / QQ(12)475476477def ch1_pow_test(sig_tuple, deg=3):478"""479Compare ch1_pow(deg) to c1^deg in Stratum(sig_tuple).480481We multiply with classes to obtain top-degree and then482evaluate.483484This should produce a series of 0s.485486Args:487sig_tuple (tuple): signature tuple488deg (int, optional): degree. Defaults to 3.489490EXAMPLES::491492sage: from admcycles.diffstrata.tests import ch1_pow_test493sage: ch1_pow_test((1,1), 2)494Calculating difference...495Products of BICs:4960 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0497Products with graphs of codim 2:4980 0 0 0499"""500X = GeneralisedStratum([Signature(sig_tuple)])501codim = X.dim() - deg502print('Calculating difference...')503c = X.chern_poly(upto=1)504diff = c[1]**deg - X.ch1_pow(deg)505if codim == 0:506print(diff.evaluate(quiet=True))507return508print('Products of BICs:')509for pr in product(range(len(X.bics)), repeat=codim):510expr = diff511for b in pr:512expr *= X.taut_from_graph((b,))513ev = expr.evaluate(quiet=True)514print(ev, end=' ')515sys.stdout.flush()516print()517if codim > 1:518print('Products with graphs of codim %r:' % codim)519for ep in X.enhanced_profiles_of_length(codim):520print((diff * X.taut_from_graph(*ep)).evaluate(quiet=True), end=' ')521sys.stdout.flush()522print()523524525def chern_poly_test(sig):526"""527Compare chern_poly and chern_class.528529We multiply with classes to obtain top-degree and then530evaluate.531532Args:533sig (tuple): signature tuple534535Returns:536bool: True537538EXAMPLES::539540sage: from admcycles.diffstrata.tests import chern_poly_test541sage: chern_poly_test((2,)) # doctest:+ELLIPSIS542Calculating Chern Polynomial via character...543Calculating difference...544Comparing top classes: 0545Comparing Products of 1 BICs and psi classes:546BIC 0 0 BIC 1 0 Psi 1 0547Comparing Products of 2 BICs and psi classes:548BIC 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 0549Products with graphs of codim 2:550Profile (..., 0) 0551All tests passed: True552True553"""554X = GeneralisedStratum([Signature(sig)])555print('Calculating Chern Polynomial via character...')556c = X.chern_poly()557print('Calculating difference...')558diff = [c[i] - X.chern_class(i) for i in reversed(range(1, X.dim() + 1))]559evs = []560for codim in range(X.dim()):561assert diff[codim].is_equidimensional()562if diff[codim].psi_list:563assert diff[codim].psi_list[0][1].degree == X.dim() - codim564if codim == 0:565print("Comparing top classes:", end=' ')566sys.stdout.flush()567ev = diff[codim].evaluate(quiet=True)568print(ev)569evs.append(ev)570continue571print('Comparing Products of %r BICs and psi classes:' % codim)572for pr in product(range(len(X.bics) + len(sig)), repeat=codim):573expr = diff[codim]574for b in pr:575if b < len(X.bics):576print('BIC %r' % b, end=' ')577expr *= X.taut_from_graph((b,))578else:579psi_num = b - len(X.bics) + 1580print('Psi %r' % psi_num, end=' ')581expr *= X.psi(psi_num)582ev = expr.evaluate(quiet=True)583print(ev, end=' ')584evs.append(ev)585sys.stdout.flush()586print()587if codim > 1:588print('Products with graphs of codim %r:' % codim)589for ep in X.enhanced_profiles_of_length(codim):590print('Profile %r' % (ep,), end=' ')591ev = (diff[codim] * X.taut_from_graph(*ep)).evaluate(quiet=True)592print(ev, end=' ')593sys.stdout.flush()594evs.append(ev)595print()596passed = all(ev == 0 for ev in evs)597print('All tests passed:', passed)598return passed599600601def chern_poly_tests(sig_list):602"""603Apply chern_poly_test to a list of signatures.604605Args:606sig_list (iterable): list of signature tuples.607608EXAMPLES::609610sage: from admcycles.diffstrata.tests import chern_poly_tests611sage: chern_poly_tests([(0,),(2,-2)])612Entering Stratum (0,)613Calculating Chern Polynomial via character...614Calculating difference...615Comparing top classes: 0616All tests passed: True617Done.618Entering Stratum (2, -2)619Calculating Chern Polynomial via character...620Calculating difference...621Comparing top classes: 0622All tests passed: True623Done.624All strata tests passed: True625"""626check_vec = []627for sig in sig_list:628print('Entering Stratum', sig)629check_vec.append(chern_poly_test(sig))630print('Done.')631print('All strata tests passed:', all(check_vec))632633634class C3_coefficient_hunter:635"""636A class that illustrates how to use symbolic variables to637test coefficients in explicit formulas of c_k.638"""639640def __init__(self, sig=None, fct=None):641self.NUM_VARS = 33642self.DEG = 3643if fct is None:644self.fct = 'c3_E'645else:646self.fct = fct647self.t = t = SR.var('t', self.NUM_VARS)648self.var_list = list(t)649self.M = None650self.constants = []651if not (sig is None):652self.add_stratum(sig)653654def add_stratum(self, sig):655X = GeneralisedStratum([Signature(sig)])656print('Calculating difference...')657expr = getattr(X, self.fct)() - X.chern_poly(upto=self.DEG)[self.DEG]658codim = X.dim() - self.DEG659if codim == 0:660self._add_eq(expr.evaluate(quiet=True))661return662print('Products of BICs and Psis:')663for pr in product(range(len(X.bics) + len(sig)), repeat=codim):664diff = expr665for b in pr:666if b < len(X.bics):667print('BIC %r' % b, end=' ')668diff *= X.taut_from_graph((b,))669else:670psi_num = b - len(X.bics) + 1671print('Psi %r' % psi_num, end=' ')672diff *= X.psi(psi_num)673ev = diff.evaluate(quiet=True)674self._add_eq(ev)675if codim > 1:676print('Products with graphs of codim %r:' % codim)677for ep in X.enhanced_profiles_of_length(codim):678print('Profile %r' % (ep,), end=' ')679self._add_eq(680(expr * X.taut_from_graph(*ep)).evaluate(quiet=True))681682def _add_eq(self, expr):683print("Adding equation: %r" % expr)684if expr == 0:685return686eqn = [expr.coefficient(v) for v in self.var_list]687cst = expr.substitute({v: 0 for v in expr.free_variables()})688if self.M is None:689self.M = Matrix(QQ, [eqn])690else:691self.M = self.M.stack(Matrix(QQ, [eqn]))692self.constants.append(cst)693694def solve(self):695self.solution = self.M.solve_right(696free_module_element(QQ, self.constants))697698def __str__(self):699s = ["Coefficient Matrix:\n"]700s.append(str(self.M))701s.append('\nRank: %r' % self.M.rank())702s.append("\nConstants:\n")703s.append(str(self.constants))704self.solve()705s.append('\nSolution:\n')706s.append(str(self.solution))707return ''.join(s)708709710class IntersectionMatrix:711"""712The intersection matrix of a stratum.713"""714715def __init__(self, sig):716"""717Initialise stratum and cache.718719Args:720sig (tuple): signature tuple721"""722self.X = Stratum(sig)723self.info_vecs = {}724self.codim_one_summary()725726@cached_method727def codim_xis(self, k):728"""729Classes of codimension k, that graphs with <= k levels730with xi powers on levels to reach deg k.731732Args:733k (int): degree734735Returns:736list: list of ELGTautClasses of deg k737"""738print('Calculating classes of codim %r...' % k, end=' ')739sys.stdout.flush()740classes = []741info_vec = []742for l in range(k + 1):743xi_deg = k - l744for ep in self.X.enhanced_profiles_of_length(l):745AG = self.X.additive_generator(ep)746# distribute xi powers:747if xi_deg == 0:748# no xis to distribute749classes.append(AG.as_taut())750info_vec.append((ep, {}))751continue752level_dims = [AG.level_dim(l) for l in range(AG.codim + 1)]753# we number the positive-dimensional levels:754pos_dim_level_dict = {}755i = 0756for l, dim in enumerate(level_dims):757if dim > 0:758pos_dim_level_dict[i] = l759i += 1760# not the most efficient way, but good enough for now:761for exponents in WeightedIntegerVectors(762xi_deg, [1] * len(pos_dim_level_dict)):763if any(exponents[i] > level_dims[pos_dim_level_dict[i]]764for i in range(len(pos_dim_level_dict))):765continue766prod = AG.as_taut()767for i, e in enumerate(exponents):768curr_xi = self.X.xi_at_level_pow(769pos_dim_level_dict[i], ep, e)770prod = self.X.intersection(prod, curr_xi, ep)771classes.append(prod)772info_vec.append(773(ep, {l: exponents[i] for i, l in pos_dim_level_dict.items()}))774print('%r found' % len(classes))775self.info_vecs[k] = info_vec776return classes777778@cached_method779def int_matrix(self, k=1):780"""781Matrix of evaluations of top-degree classes (products of codim_xis(k)782and codim_xis(dim-k)).783784Args:785k (int, optional): degree. Defaults to 1.786787Returns:788list: list of lists of rational numbers.789"""790x_classes = self.codim_xis(k)791y_classes = self.codim_xis(self.X.dim() - k)792M = [[self.X.ZERO for _ in range(len(y_classes))]793for _ in range(len(x_classes))]794print('Calculating intersection matrix for codim %r...' % k, end=' ')795sys.stdout.flush()796for i, x in enumerate(x_classes):797for j, y in enumerate(y_classes):798prod = x * y799assert prod.is_equidimensional()800assert prod == self.X.ZERO or prod.psi_list[0][1].degree == self.X.dim(801)802M[i][j] = (prod).evaluate()803print('Done!')804return M805806def codim_one_summary(self):807"""808Display codim 1 matrix summary.809"""810print(self.X)811M = self.int_matrix(1)812rk = Matrix(M).rank()813print('Codim 1: Rank of %r x %r matrix: %r' % (len(M), len(M[0]), rk))814815def summary(self):816"""817Summary of matrices in all codimensions.818"""819print(self.X)820for k in range(self.X.dim() + 1):821M = self.int_matrix(k)822rk = Matrix(M).rank()823print('Codim %r: Rank of %r x %r matrix: %r' %824(k, len(M), len(M[0]), rk))825826def print_matrix(self, k=1):827"""828Human readable output of int_matrix(k) values.829830Args:831k (int, optional): degree. Defaults to 1.832"""833for row in range(len(self.int_matrix(k))):834self.print_row(row + 1, k)835836def info(self, i, k=1):837"""838A string representation of the i-th codim k class.839840Args:841i (int): index of codim_xis(k)842k (int, optional): degree. Defaults to 1.843844Returns:845String: string description of which levels carry xis.846"""847if k not in self.info_vecs:848self.codim_xis(k)849ep, d = self.info_vecs[k][i]850s = str(ep)851for l, e in d.items():852s += ' level %r: xi^%r,' % (l, e)853return s854855def entry(self, row, col, k=1):856"""857Human-readable representation of the entry row, col of int_matrix(k).858859Note that this prints the classes being multiplied, not the values.860861Args:862row (int): row index (math notation, i.e. starting at 1)863col (int): col index (math notation, i.e. starting at 1)864k (int, optional): degree. Defaults to 1.865866Returns:867String: info of the two factors at this entry868"""869# math notation, i.e. starting at 1!!870return self.info(row - 1, k) + ' * ' + self.info(col - 1, self.X.dim() - k)871872def print_row(self, row, k=1):873"""874Human-readable output of the row of int_matrix(k)875876Args:877row (int): row (math notation, i.e. starting at 1)878k (int, optional): degree. Defaults to 1.879"""880# use math notation, i.e. starting at 1!!881M = self.int_matrix(k)882print("Row %r" % row)883for col, value in enumerate(M[row - 1]):884print('Col %r: %s value: %r' %885(col + 1, self.entry(row, col + 1, k), value))886887def print_col(self, col, k=1):888"""889Human-readable output of the col of int_matrix(k)890891Args:892col (int): column (math notation, i.e. starting at 1)893k (int, optional): degree. Defaults to 1.894"""895# use math notation, i.e. starting at 1!!896M = self.int_matrix(k)897print("Col %r" % col)898for row in range(len(M)):899print('Row %r: %s value: %r' %900(row + 1, self.entry(row + 1, col, k), M[row][col - 1]))901902#########################################903904905def push_pull(sig, T_name=None):906print('Testing non-horizontal push-pull for stratum %r' % (sig,), end=' ')907sys.stdout.flush()908X = Stratum(sig)909if T_name == 'xi':910print('using xi:')911T = X.xi912else:913T = X.ONE914print('using [1]:')915g = X._g[0]916n = X._n917for G in admcycles.admcycles.list_strata(g, n, 1):918if len(G.genera()) == 1:919# horizontal920continue921print("%r: " % G, end='')922sys.stdout.flush()923pullback = X.boundary_pullback(G)924if pullback == X.ZERO:925print('ZERO')926else:927LHS = (T * pullback).to_prodtautclass().pushforward()928RHS = admcycles.admcycles.tautclass(929[admcycles.admcycles.decstratum(G)]) * T.to_prodtautclass().pushforward()930print((LHS - RHS).is_zero())931932933