| Download
Project: admcycles
Views: 724Visibility: Unlisted (only visible to those who know the link)
Image: ubuntu2004from __future__ import print_function1from __future__ import print_function23import sys45from itertools import product67from sympy.utilities.iterables import partitions89from sage.rings.rational_field import QQ # pylint: disable=import-error10from sage.arith.functions import lcm # pylint: disable=import-error11from sage.arith.misc import gcd # pylint: disable=import-error12from sage.symbolic.ring import SR # pylint: disable=import-error13from sage.matrix.constructor import Matrix # pylint: disable=import-error14from sage.modules.free_module_element import free_module_element # pylint: disable=import-error15from sage.combinat.integer_vector_weighted import WeightedIntegerVectors # pylint: disable=import-error16from sage.misc.cachefunc import cached_method # pylint: disable=import-error1718from admcycles.diffstrata.levelstratum import GeneralisedStratum, Stratum19from admcycles.diffstrata.sig import Signature2021# from admcycles import list_strata, Strataclass2223def test_calL(sig):24"""25Compare calL and the 'error term' of cnb.2627EXAMPLES ::2829sage: from admcycles.diffstrata.tests import test_calL30sage: test_calL((1,1,1,1,-6))31sage: test_calL((4,))32"""33X = GeneralisedStratum([Signature(sig)])34for i, B in enumerate(X.bics):35ll = lcm(B.LG.prongs.values())36assert 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.ZERO3738def meromorphic_tests():39"""40EXAMPLES ::4142sage: from admcycles.diffstrata import *43sage: X=GeneralisedStratum([Signature((1,1,1,1,-6))])44sage: (X.xi^2).evaluate(quiet=True)45254647sage: X=GeneralisedStratum([Signature((-2,-2,-2,-2,6))])48sage: (X.xi^X.dim()).evaluate(quiet=True)49305051Testing normal bundles:5253sage: X=GeneralisedStratum([Signature((2,2,-2))])54sage: td0 = X.taut_from_graph((0,))55sage: td1 = X.taut_from_graph((1,))56sage: td4 = X.taut_from_graph((4,))57sage: td5 = X.taut_from_graph((5,))58sage: td8 = X.taut_from_graph((8,))59sage: assert X.ZERO == td0^2*td1 - td0*td1*td0 # not 'safe' # doctest:+SKIP60sage: assert X.ZERO == td0^2*td5 - td0*td5*td0 # not 'safe' # doctest:+SKIP61sage: assert X.ZERO == td0^2*td8 - td0*td8*td0 # not 'safe' # doctest:+SKIP62sage: assert (td8^3*td4).evaluate(quiet=True) == (td8^2*td4*td8).evaluate(quiet=True) == (td8*td4*td8^2).evaluate(quiet=True)6364"""65pass6667def gengenustwotests():68"""69EXAMPLES ::7071sage: from admcycles.diffstrata import *72sage: X=GeneralisedStratum([Signature((2,))])73sage: assert (X.xi^X.dim()).evaluate(quiet=True) == -1/64074sage: ct=[i for i, B in enumerate(X.bics) if len(B.LG.edges) == 1]75sage: ct_index = ct[0] # compact type graph76sage: ct_taut = X.taut_from_graph((ct_index,))77sage: assert (X.c2_E*ct_taut).evaluate(quiet=True) == 1/4878sage: banana_index = 1 - ct_index # only 2 BICs!79sage: banana_taut = X.taut_from_graph((banana_index,))80sage: assert (X.c2_E*banana_taut).evaluate(quiet=True) == 1/2481sage: assert (X.c1_E*banana_taut**2).evaluate(quiet=True) == -1/1682sage: assert (X.c1_E*banana_taut*ct_taut).evaluate(quiet=True) == 1/2483sage: assert (X.c1_E*ct_taut**2).evaluate(quiet=True) == -1/4884sage: assert (ct_taut**3).evaluate(quiet=True) == 1/9685sage: assert (banana_taut**3).evaluate(quiet=True) == 1/4886sage: assert (ct_taut*banana_taut**2).evaluate(quiet=True) == 087sage: assert (ct_taut*ct_taut*banana_taut).evaluate(quiet=True) == -1/488889sage: X=GeneralisedStratum([Signature((1,1))])90sage: at1 = X.taut_from_graph((1,))91sage: at2 = X.taut_from_graph((2,))92sage: X.ZERO == at1^2*at2 + (-1)*at1*at2*at193True94sage: X.ZERO == (-1)*(at1+at2)^3*at2 + at1^3*at2 + 3*at1^2*at2*at2 + 3*at1*at2^2*at2 + at2^3*at295True96sage: X.ZERO == (-1)*(at1+at2)^4 + at1^4 + 4*at1^3*at2 + 6*at1^2*at2^2 + 4*at1^1*at2^3 + at2^497True98sage: (X.xi^X.dim()).evaluate(quiet=True)990100sage: psi1 = AdditiveGenerator(X,((),0),{1:1}).as_taut()101sage: (X.xi^3*psi1).evaluate(quiet=True)102-1/360103"""104pass105106def 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"""126pass127128def genusfourtests():129"""130Tests in H(6): (think of smart NB test...)131132EXAMPLES ::133134sage: from admcycles.diffstrata import *135136"""137pass138139class BananaSuite:140"""141A frontend for the Stratum (k, 1, -k-1).142143This class models the situation of sec 10.2 of CMZ20144with a method D for accessing the divisors in the145notation of loc. cit. (either D(i), i=2,3,4 or D(i,a)146for i=1,5).147"""148def __init__(self,k):149"""150Initialise the genus 1 stratum (k, 1, -k-1).151152Args:153k (int): order of zero154"""155self._k = k156self._X = GeneralisedStratum([Signature((k,1,-k-1))])157158def D(self,i,a=1):159"""160The divisor using the notation of Sec. 10.2.161162Args:163i (int): index 1,2,3,4,5164a (int, optional): prong for i=1 or 5. Defaults to 1.165166Returns:167ELGTautClass: Tautological class of the divisor D_{i,a}.168"""169if i == 1:170for b,B in enumerate(self._X.bics):171v = B.LG.verticesonlevel(0)[0]172if (B.LG.genus(v) == 0 and173len(B.LG.ordersonvertex(v)) == 3 and174len(B.LG.edges) == 2 and175a in B.LG.prongs.values()):176assert -self._k-1 in B.LG.ordersonvertex(v),\177"%r" % B178return self._X.taut_from_graph((b,))179elif i == 2:180for b,B in enumerate(self._X.bics):181v = B.LG.verticesonlevel(0)[0]182if (B.LG.genus(v) == 1 and len(B.LG.ordersonvertex(v)) == 2):183assert -self._k-1 in B.LG.ordersonvertex(v),\184"%r" % B185return self._X.taut_from_graph((b,))186elif i == 3:187for b,B in enumerate(self._X.bics):188v = B.LG.verticesonlevel(0)[0]189if (B.LG.genus(v) == 1 and len(B.LG.ordersonvertex(v)) == 1):190return self._X.taut_from_graph((b,))191elif i == 4:192for b,B in enumerate(self._X.bics):193v = B.LG.verticesonlevel(-1)[0]194if (B.LG.genus(v) == 1 and len(B.LG.ordersonvertex(v)) == 2):195return self._X.taut_from_graph((b,))196elif i == 5:197for b,B in enumerate(self._X.bics):198v = B.LG.verticesonlevel(0)[0]199if (B.LG.genus(v) == 0 and200len(B.LG.ordersonvertex(v)) == 4 and201len(B.LG.edges) == 2 and202a in B.LG.prongs.values()):203assert -self._k-1 in B.LG.ordersonvertex(v),\204"%r" % B205return self._X.taut_from_graph((b,))206else:207return None208209def check(self,quiet=False):210"""211Check Prop 10.1212213Args:214quiet (bool, optional): No output. Defaults to False.215216Returns:217bool: Should always return True.218"""219check_list = []220def delta(k,a):221if a == k/2:222return QQ(1)/QQ(2)223else:224return 1225for a in range(1,self._k+1):226si = (self.D(1,a)**2).evaluate(quiet=True)227rhs = -QQ(delta(self._k+1,a)*self._k*gcd(a,self._k+1-a))/QQ(lcm(a,self._k+1-a))228check_list.append(si == rhs)229if not quiet:230print("D(1,%r)^2 = %r, RHS = %r" % (a,si,rhs))231for a in range(1,self._k):232si = (self.D(5,a)**2).evaluate(quiet=True)233rhs = -QQ(delta(self._k,a)*(self._k+1)*gcd(a,self._k-a))/QQ(lcm(a,self._k-a))234check_list.append(si == rhs)235if not quiet:236print("D(5,%r)^2 = %r, RHS = %r" % (a,si,rhs))237return all(check_list)238239def banana_tests(self):240"""241EXAMPLES ::242243sage: from admcycles.diffstrata.tests import BananaSuite244sage: B=BananaSuite(2)245sage: B.check(quiet=True)246True247sage: (B._X.xi**2).evaluate(quiet=True) == QQ(2**4 - 1)/QQ(24)248True249sage: assert((B._X.xi_with_leg(quiet=True)*B.D(5,1)).evaluate(quiet=True) == \250B._X.xi_at_level(0,B.D(5,1).psi_list[0][1].enh_profile,quiet=True).evaluate(quiet=True) == -1)251sage: 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)252253sage: B=BananaSuite(5)254sage: B.check(quiet=True)255True256sage: B=BananaSuite(5)257sage: (B._X.xi**2).evaluate(quiet=True) == QQ(5**4 - 1)/QQ(24)258True259260sage: B=BananaSuite(6)261sage: assert((B._X.xi_with_leg(quiet=True)*B.D(5,2)).evaluate(quiet=True) == \262B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=1,quiet=True).evaluate(quiet=True) == \263B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=2,quiet=True).evaluate(quiet=True) == \264B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=3,quiet=True).evaluate(quiet=True) == \265B._X.xi_at_level(0,B.D(5,2).psi_list[0][1].enh_profile,leg=4,quiet=True).evaluate(quiet=True) == -12)266267sage: B=BananaSuite(10)268sage: B.check(quiet=True)269True270sage: (B._X.xi**2).evaluate(quiet=True) == QQ(10**4 - 1)/QQ(24)271True272"""273pass274275def rGRCtests():276"""277Test the surjectivity of the _to_bic maps.278279EXAMPLES ::280281sage: from admcycles.diffstrata import *282sage: X=GeneralisedStratum([Signature((2,2,-2))])283sage: 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)))284sage: 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)))285"""286pass287288def middle_level_degeneration(sig):289"""290Check if gluing in middle bics gives (at least as a set) all length three profiles.291292Maybe think of some more sophisticated test...293294Args:295sig (tuple): Signature tuple.296297EXAMPLES ::298299sage: from admcycles.diffstrata.tests import middle_level_degeneration300sage: middle_level_degeneration((1,1))301sage: middle_level_degeneration((2,2,-2))302sage: middle_level_degeneration((4,))303sage: middle_level_degeneration((2,2,2,-6))304"""305X = GeneralisedStratum([Signature(sig)])306three_level_graphs = X.enhanced_profiles_of_length(2)307four_level_profiles_set = set(X.lookup_list[3])308seen = set()309for ep in three_level_graphs:310p, _i = ep311for b in X.DG.middle_to_bic(ep).values():312seen.add((p[0],b,p[1]))313assert seen == four_level_profiles_set314315def leg_test(sig,quiet=False):316"""317Tests on each dimension 1 graphs of the stratum with signature sig:318We test on each one-dimensional level if the evaluation of the xi glued in at319that level is the same (for every leg!) as the product of the graph with xi on320the whole stratum.321322Args:323sig (tuple): Signature of a stratum.324quiet (bool, optional): No output. Defaults to False.325326EXAMPLES ::327328sage: from admcycles.diffstrata.tests import leg_test329sage: leg_test((6,1,-7),quiet=True)330sage: leg_test((3,-1,-2),quiet=True)331sage: leg_test((1,1),quiet=True)332sage: leg_test((2,2,-2),quiet=True) # long time333"""334X=GeneralisedStratum([Signature(sig)])335d = X.dim() - 1 # codim336for p in X.lookup_list[d]:337components = X.lookup(p)338for i, B in enumerate(components):339enh_profile = (p,i)340global_xi_prod = (X.xi_with_leg(quiet=True)*X.taut_from_graph(p,i)).evaluate(quiet=True)341top_dim = X.lookup_graph(*enh_profile).level(0).dim()342if not quiet:343print("Graph %r: xi evaluated: %r (dim of Level 0: %r)" % (enh_profile,global_xi_prod,top_dim))344if top_dim == 0:345assert global_xi_prod == 0346for l in range(d):347L = B.level(l)348if L.dim() != 1:349continue350first = None351for leg in L.leg_dict:352level_xi_prod = X.xi_at_level(l,(p,i),leg=leg,quiet=True).evaluate(quiet=True)353if not first:354first = level_xi_prod355if not quiet:356print("level: %r, leg: %r, xi ev: %r" % (l, leg, level_xi_prod))357if quiet:358assert first == level_xi_prod359if l == 0:360assert global_xi_prod == level_xi_prod361362def stratumclasstests():363"""364Tests of stratum class calculations.365366EXAMPLES ::367368sage: from admcycles.diffstrata import *369370sage: X=GeneralisedStratum([Signature((23,5,-13,-17))])371sage: assert X.res_stratum_class([(0,2)]).evaluate(quiet=True) == 5372"""373pass374375def commutativity_check(sig):376"""377Run a (large) commutativity check on Stratum(sig)378to check the normal bundle.379380More precisely, we check all top-degree products381of BICs in this stratum, multiplying them from382right-to-left and from left-to-right and checking383that the evaluations agree.384385Args:386sig (tuple): signature tuple387388Raises:389RuntimeError: raised if a commutator doesn't390evaluate to 0.391"""392X=GeneralisedStratum([Signature(sig)])393n = X.dim()394for T in product(range(len(X.bics)),repeat=n):395print("Starting IPs")396print(T)397PR = X.taut_from_graph((T[0],))398RP = X.taut_from_graph((T[-1],))399for i in range(1,n):400PR *= X.taut_from_graph((T[i],))401RP *= X.taut_from_graph((T[-1-i],))402print(T[0],T[1])403RP = RP.evaluate(quiet=True)404PR = PR.evaluate(quiet=True)405if PR - RP != 0:406print(T, " gives ",PR-RP)407raise RuntimeError408409def c2_banana_tests(k):410"""411Check c2 evaluation for the bananas.412413Args:414k (int): zero of the banana415416Returns:417RationalNumber: difference of evaluate of c2 and c2418formula in terms of c1 and ch2 (should be 0!!!)419420EXAMPLES ::421422sage: from admcycles.diffstrata.tests import c2_banana_tests423sage: for k in range(1,10): assert c2_banana_tests(k) == 0424"""425X=GeneralisedStratum([Signature((-k-1,k,1))])426assert (X.c2_E).evaluate(quiet=True) == QQ(k*(k+1))/QQ(6)427return (X.c2_E).evaluate(quiet=True) - QQ(1)/QQ(2)*(X.c1_E**2 + (-2)*X.ch2_E).evaluate(quiet=True)428429def c2_test(sig):430"""431Compare c2_E to (ch_1^2 - 2ch_2)/2.432433EXAMPLES ::434435sage: from admcycles.diffstrata.tests import c2_test436sage: assert c2_test((1,1,1,1,-6)) == 2437sage: assert c2_test((-2,-2,-2,-2,6)) == 2438"""439X=GeneralisedStratum([Signature(sig)])440c2ev = (X.c2_E).evaluate(quiet=True)441diff = c2ev - QQ(1)/QQ(2)*(X.c1_E**2 + (-2)*X.ch2_E).evaluate(quiet=True)442assert diff == 0443return c2ev444445def c1_test(k):446"""447Check the Euler characteristic of (k,-k) (modular curves).448449EXAMPLES ::450451sage: from admcycles.diffstrata.tests import c1_test452sage: for k in range(2,20): assert c1_test(k)453"""454X=GeneralisedStratum([Signature((k,-k))])455return (X.c1_E).evaluate(quiet=True) == QQ(k*k - 1)/QQ(12)456457def ch1_pow_test(sig_tuple, deg=3):458"""459Compare ch1_pow(deg) to c1^deg in Stratum(sig_tuple).460461We multiply with classes to obtain top-degree and then462evaluate.463464This should produce a series of 0s.465466Args:467sig_tuple (tuple): signature tuple468deg (int, optional): degree. Defaults to 3.469470EXAMPLES ::471472sage: from admcycles.diffstrata.tests import ch1_pow_test473sage: ch1_pow_test((1,1), 2)474Calculating difference...475Products of BICs:4760 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0477Products with graphs of codim 2:4780 0 0 0479"""480X = GeneralisedStratum([Signature(sig_tuple)])481codim = X.dim() - deg482print('Calculating difference...')483c = X.chern_poly(upto=1)484diff = c[1]**deg - X.ch1_pow(deg)485if codim == 0:486print(diff.evaluate(quiet=True))487return488print('Products of BICs:')489for pr in product(range(len(X.bics)),repeat=codim):490expr = diff491for b in pr:492expr *= X.taut_from_graph((b,))493ev = expr.evaluate(quiet=True)494print(ev, end=' ')495sys.stdout.flush()496print()497if codim > 1:498print('Products with graphs of codim %r:' % codim)499for ep in X.enhanced_profiles_of_length(codim):500print((diff*X.taut_from_graph(*ep)).evaluate(quiet=True), end=' ')501sys.stdout.flush()502print()503504def chern_poly_test(sig):505"""506Compare chern_poly and chern_class.507508We multiply with classes to obtain top-degree and then509evaluate.510511Args:512sig (tuple): signature tuple513514Returns:515bool: True516517EXAMPLES ::518519sage: from admcycles.diffstrata.tests import chern_poly_test520sage: chern_poly_test((2,)) # doctest:+ELLIPSIS521Calculating Chern Polynomial via character...522Calculating difference...523Comparing top classes: 0524Comparing Products of 1 BICs and psi classes:525BIC 0 0 BIC 1 0 Psi 1 0526Comparing Products of 2 BICs and psi classes:527BIC 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 0528Products with graphs of codim 2:529Profile (..., 0) 0530All tests passed: True531True532"""533X = GeneralisedStratum([Signature(sig)])534print('Calculating Chern Polynomial via character...')535c = X.chern_poly()536print('Calculating difference...')537diff = [c[i] - X.chern_class(i) for i in reversed(range(1, X.dim() + 1))]538evs = []539for codim in range(X.dim()):540assert diff[codim].is_equidimensional()541if diff[codim].psi_list:542assert diff[codim].psi_list[0][1].degree == X.dim() - codim543if codim == 0:544print("Comparing top classes:", end=' ')545sys.stdout.flush()546ev = diff[codim].evaluate(quiet=True)547print(ev)548evs.append(ev)549continue550print('Comparing Products of %r BICs and psi classes:' % codim)551for pr in product(range(len(X.bics) + len(sig)),repeat=codim):552expr = diff[codim]553for b in pr:554if b < len(X.bics):555print('BIC %r' % b, end=' ')556expr *= X.taut_from_graph((b,))557else:558psi_num = b - len(X.bics) + 1559print('Psi %r' % psi_num, end=' ')560expr *= X.psi(psi_num)561ev = expr.evaluate(quiet=True)562print(ev, end=' ')563evs.append(ev)564sys.stdout.flush()565print()566if codim > 1:567print('Products with graphs of codim %r:' % codim)568for ep in X.enhanced_profiles_of_length(codim):569print('Profile %r' % (ep,), end=' ')570ev = (diff[codim]*X.taut_from_graph(*ep)).evaluate(quiet=True)571print(ev, end=' ')572sys.stdout.flush()573evs.append(ev)574print()575passed = all(ev == 0 for ev in evs)576print('All tests passed:', passed)577return passed578579def chern_poly_tests(sig_list):580"""581Apply chern_poly_test to a list of signatures.582583Args:584sig_list (iterable): list of signature tuples.585586EXAMPLES ::587588sage: from admcycles.diffstrata.tests import chern_poly_tests589sage: chern_poly_tests([(0,),(2,-2)])590Entering Stratum (0,)591Calculating Chern Polynomial via character...592Calculating difference...593Comparing top classes: 0594All tests passed: True595Done.596Entering Stratum (2, -2)597Calculating Chern Polynomial via character...598Calculating difference...599Comparing top classes: 0600All tests passed: True601Done.602All strata tests passed: True603"""604check_vec = []605for sig in sig_list:606print('Entering Stratum', sig)607check_vec.append(chern_poly_test(sig))608print('Done.')609print('All strata tests passed:', all(check_vec))610611class C3_coefficient_hunter:612"""613A class that illustrates how to use symbolic variables to614test coefficients in explicit formulas of c_k.615"""616def __init__(self, sig=None, fct=None):617self.NUM_VARS = 33618self.DEG = 3619if fct is None:620self.fct = 'c3_E'621else:622self.fct = fct623self.t = t = SR.var('t', self.NUM_VARS)624self.var_list = list(t)625self.M = None626self.constants = []627if not (sig is None):628self.add_stratum(sig)629630def add_stratum(self, sig):631X = GeneralisedStratum([Signature(sig)])632print('Calculating difference...')633expr = getattr(X, self.fct)() - X.chern_poly(upto=self.DEG)[self.DEG]634codim = X.dim() - self.DEG635if codim == 0:636self._add_eq(expr.evaluate(quiet=True))637return638print('Products of BICs and Psis:')639for pr in product(range(len(X.bics) + len(sig)),repeat=codim):640diff = expr641for b in pr:642if b < len(X.bics):643print('BIC %r' % b, end=' ')644diff *= X.taut_from_graph((b,))645else:646psi_num = b - len(X.bics) + 1647print('Psi %r' % psi_num, end=' ')648diff *= X.psi(psi_num)649ev = diff.evaluate(quiet=True)650self._add_eq(ev)651if codim > 1:652print('Products with graphs of codim %r:' % codim)653for ep in X.enhanced_profiles_of_length(codim):654print('Profile %r' % (ep,), end=' ')655self._add_eq((expr*X.taut_from_graph(*ep)).evaluate(quiet=True))656657def _add_eq(self, expr):658print("Adding equation: %r" % expr)659if expr == 0:660return661eqn = [expr.coefficient(v) for v in self.var_list]662cst = expr.substitute({v : 0 for v in expr.free_variables()})663if self.M is None:664self.M = Matrix(QQ,[eqn])665else:666self.M = self.M.stack(Matrix(QQ,[eqn]))667self.constants.append(cst)668669def solve(self):670self.solution = self.M.solve_right(free_module_element(QQ, self.constants))671672def __str__(self):673s=["Coefficient Matrix:\n"]674s.append(str(self.M))675s.append('\nRank: %r' % self.M.rank())676s.append("\nConstants:\n")677s.append(str(self.constants))678self.solve()679s.append('\nSolution:\n')680s.append(str(self.solution))681return ''.join(s)682683class IntersectionMatrix:684"""685The intersection matrix of a stratum.686"""687def __init__(self, sig):688"""689Initialise stratum and cache.690691Args:692sig (tuple): signature tuple693"""694self.X = Stratum(sig)695self.info_vecs = {}696self.codim_one_summary()697698@cached_method699def codim_xis(self, k):700"""701Classes of codimension k, that graphs with <= k levels702with xi powers on levels to reach deg k.703704Args:705k (int): degree706707Returns:708list: list of ELGTautClasses of deg k709"""710print('Calculating classes of codim %r...' % k, end=' ')711sys.stdout.flush()712classes = []713info_vec = []714for l in range(k+1):715xi_deg = k - l716for ep in self.X.enhanced_profiles_of_length(l):717AG = self.X.additive_generator(ep)718# distribute xi powers:719if xi_deg == 0:720# no xis to distribute721classes.append(AG.as_taut())722info_vec.append((ep, {}))723continue724level_dims = [AG.level_dim(l) for l in range(AG.codim + 1)]725# we number the positive-dimensional levels:726pos_dim_level_dict = {}727i = 0728for l, dim in enumerate(level_dims):729if dim > 0:730pos_dim_level_dict[i] = l731i += 1732# not the most efficient way, but good enough for now:733for exponents in WeightedIntegerVectors(xi_deg, [1]*len(pos_dim_level_dict)):734if any(exponents[i] > level_dims[pos_dim_level_dict[i]] for i in range(len(pos_dim_level_dict))):735continue736prod = AG.as_taut()737for i, e in enumerate(exponents):738curr_xi = self.X.xi_at_level_pow(pos_dim_level_dict[i], ep, e)739prod = self.X.intersection(prod, curr_xi, ep)740classes.append(prod)741info_vec.append((ep, {l : exponents[i] for i, l in pos_dim_level_dict.items()}))742print('%r found' % len(classes))743self.info_vecs[k] = info_vec744return classes745746@cached_method747def int_matrix(self, k=1):748"""749Matrix of evaluations of top-degree classes (products of codim_xis(k)750and codim_xis(dim-k)).751752Args:753k (int, optional): degree. Defaults to 1.754755Returns:756list: list of lists of rational numbers.757"""758x_classes = self.codim_xis(k)759y_classes = self.codim_xis(self.X.dim() - k)760M = [[self.X.ZERO for _ in range(len(y_classes))] for _ in range(len(x_classes))]761print('Calculating intersection matrix for codim %r...' % k, end=' ')762sys.stdout.flush()763for i, x in enumerate(x_classes):764for j, y in enumerate(y_classes):765prod = x*y766assert prod.is_equidimensional()767assert prod == self.X.ZERO or prod.psi_list[0][1].degree == self.X.dim()768M[i][j] = (prod).evaluate()769print('Done!')770return M771772def codim_one_summary(self):773"""774Display codim 1 matrix summary.775"""776print(self.X)777M = self.int_matrix(1)778rk = Matrix(M).rank()779print('Codim 1: Rank of %r x %r matrix: %r' % (len(M), len(M[0]), rk))780781def summary(self):782"""783Summary of matrices in all codimensions.784"""785print(self.X)786for k in range(self.X.dim() + 1):787M = self.int_matrix(k)788rk = Matrix(M).rank()789print('Codim %r: Rank of %r x %r matrix: %r' % (k, len(M), len(M[0]), rk))790791def print_matrix(self, k=1):792"""793Human readable output of int_matrix(k) values.794795Args:796k (int, optional): degree. Defaults to 1.797"""798for row in range(len(self.int_matrix(k))):799self.print_row(row+1, k)800801def info(self, i, k=1):802"""803A string representation of the i-th codim k class.804805Args:806i (int): index of codim_xis(k)807k (int, optional): degree. Defaults to 1.808809Returns:810String: string description of which levels carry xis.811"""812if k not in self.info_vecs:813self.codim_xis(k)814ep, d = self.info_vecs[k][i]815s = str(ep)816for l, e in d.items():817s += ' level %r: xi^%r,' % (l, e)818return s819820def entry(self, row, col, k=1):821"""822Human-readable representation of the entry row, col of int_matrix(k).823824Note that this prints the classes being multiplied, not the values.825826Args:827row (int): row index (math notation, i.e. starting at 1)828col (int): col index (math notation, i.e. starting at 1)829k (int, optional): degree. Defaults to 1.830831Returns:832String: info of the two factors at this entry833"""834# math notation, i.e. starting at 1!!835return self.info(row-1, k) + ' * ' + self.info(col-1, self.X.dim()-k)836837def print_row(self, row, k=1):838"""839Human-readable output of the row of int_matrix(k)840841Args:842row (int): row (math notation, i.e. starting at 1)843k (int, optional): degree. Defaults to 1.844"""845## use math notation, i.e. starting at 1!!846M = self.int_matrix(k)847print("Row %r" % row)848for col, value in enumerate(M[row-1]):849print('Col %r: %s value: %r' % (col+1, self.entry(row, col+1, k), value))850851def print_col(self, col, k=1):852"""853Human-readable output of the col of int_matrix(k)854855Args:856col (int): column (math notation, i.e. starting at 1)857k (int, optional): degree. Defaults to 1.858"""859## use math notation, i.e. starting at 1!!860M = self.int_matrix(k)861print("Col %r" % col)862for row in range(len(M)):863print('Row %r: %s value: %r' % (row+1, self.entry(row+1, col, k), M[row][col-1]))864865866