Ticket #6911: 6911-hecke-basis-disc.patch

File 6911-hecke-basis-disc.patch, 7.2 KB (added by robertwb, 13 years ago)
  • sage/matrix/matrix2.pyx

    # HG changeset patch
    # User Robert Bradshaw <robertwb@math.washington.edu>
    # Date 1252561710 25200
    # Node ID 282ed7ea92458f757aeae4b8940ce7819f8df959
    # Parent  92b42ec2270c48679428f4da160e1f11847cef0f
    #6911 Faster basis for Hecke algebras.
    
    diff -r 92b42ec2270c -r 282ed7ea9245 sage/matrix/matrix2.pyx
    a b  
    13251325        for i from 0 <= i < self._nrows:
    13261326            s = s + self.get_unsafe(i,i)
    13271327        return s
     1328   
     1329    def trace_of_product(self, Matrix other):
     1330        """
     1331        Returns the trace of self * other without computing the entire product.
     1332       
     1333        EXAMPLES::
     1334           
     1335            sage: M = random_matrix(ZZ, 10, 20)
     1336            sage: N = random_matrix(ZZ, 20, 10)
     1337            sage: M.trace_of_product(N)
     1338            -1629
     1339            sage: (M*N).trace()
     1340            -1629
     1341        """
     1342        if self._nrows != other._ncols or other._nrows != self._ncols:
     1343            raise ArithmeticError, "incompatible dimensions"
     1344        s = self._base_ring(0)
     1345        for i from 0 <= i < self._nrows:
     1346            for j from 0 <= j < self._ncols:
     1347                s += self.get_unsafe(i, j) * other.get_unsafe(j, i)
     1348        return s
    13281349
    13291350    #####################################################################################
    13301351    # Generic Hessenberg Form and charpoly algorithm
  • sage/modular/hecke/algebra.py

    diff -r 92b42ec2270c -r 282ed7ea9245 sage/modular/hecke/algebra.py
    a b  
    3131import math
    3232import weakref
    3333
    34 import sage.rings.all as rings
    3534import sage.rings.arith as arith
    3635import sage.rings.infinity
    3736import sage.misc.latex as latex
     
    4342from sage.matrix.constructor import matrix
    4443from sage.rings.arith import lcm
    4544from sage.matrix.matrix_space import MatrixSpace
     45from sage.rings.all import ZZ, QQ
    4646
    4747def is_HeckeAlgebra(x):
    4848    r"""
     
    168168        [0 1]
    169169        [0 5]]
    170170    """
    171     QQ = rings.QQ
    172     ZZ = rings.ZZ
    173171    d = M.rank()
    174172    VV = QQ**(d**2)
    175173    WW = ZZ**(d**2)
     
    217215        [0 1]
    218216        [0 5]]
    219217    """
    220     QQ = rings.QQ
    221     ZZ = rings.ZZ
    222218    d = M.rank()
    223219    VV = QQ**(d**2)
    224220    WW = ZZ**(d**2)
     
    520516        try:
    521517            return self.__basis_cache
    522518        except AttributeError:
    523             self.__basis_cache=_heckebasis(self.__M)
     519            pass
     520        level = self.level()
     521        bound = self.__M.hecke_bound()
     522        dim = self.__M.rank()
     523        span = [self.hecke_operator(n) for n in range(2, bound+1) if not self.is_anemic() or gcd(n, level) == 1]
     524        rand_max = 5
     525        while True:
     526            # Project the full Hecke module to a random submodule to ease the HNF reduction.
     527            v = (ZZ**dim).random_element(x=rand_max)
     528            proj_span = matrix([T.matrix()*v for T in span])._clear_denom()[0]
     529            proj_basis = proj_span.hermite_form()
     530            if proj_basis[dim-1] == 0:
     531                # We got unlucky, choose another projection.
     532                rand_max *= 2
     533                continue
     534            # Lift the projected basis to a basis in the Hecke algebra.
     535            trans = proj_span.solve_left(proj_basis)
     536            self.__basis_cache = [sum(c*T for c,T in zip(row,span) if c != 0) for row in trans[:dim]]
    524537            return self.__basis_cache
    525538
    526539    def discriminant(self):
     
    535548        *Conjectures about discriminants of Hecke algebras of prime
    536549        level*, Springer LNCS 3076.
    537550       
    538         Not implemented at present.
    539        
    540551        EXAMPLE::
    541552
    542553            sage: BrandtModule(3, 4).hecke_algebra().discriminant()
    543             Traceback (most recent call last):
    544             ...
    545             NotImplementedError
     554            1
     555            sage: ModularSymbols(65, sign=1).cuspidal_submodule().hecke_algebra().discriminant()
     556            6144
    546557        """
    547         raise NotImplementedError
     558        try:
     559            return self.__disc
     560        except AttributeError:
     561            pass
     562        basis = self.basis()
     563        d = len(self.basis())
     564        trace_matrix = matrix(ZZ, d)
     565        for i in range(d):
     566            for j in range(i+1):
     567                trace_matrix[i,j] = trace_matrix[j,i] = basis[i].matrix().trace_of_product(basis[j].matrix())
     568        self.__disc = trace_matrix.det()
     569        return self.__disc
    548570
    549571    def gens(self):
    550572        r"""
  • sage/modular/hecke/ambient_module.py

    diff -r 92b42ec2270c -r 282ed7ea9245 sage/modular/hecke/ambient_module.py
    a b  
    477477        generate the full Hecke algebra as a module over the base ring. Note
    478478        that we include the `n` with `n` not coprime to the level.
    479479
    480         At present this returns an unproven guess which appears to be valid for
    481         `M_k(\Gamma_0(N))`, where k and N are the weight and level of self. (It
    482         is clearly valid for *cuspidal* spaces of any fixed character, as a
    483         consequence of the Sturm bound theorem.) It returns a hopelessly wrong
    484         answer for spaces of full level `\Gamma_1`.
     480        At present this returns an unproven guess for non-cuspidal spaces which
     481        appears to be valid for `M_k(\Gamma_0(N))`, where k and N are the
     482        weight and level of self. (It is clearly valid for *cuspidal* spaces
     483        of any fixed character, as a consequence of the Sturm bound theorem.)
     484        It returns a hopelessly wrong answer for spaces of full level
     485        `\Gamma_1`.
    485486
    486487        TODO: Get rid of this dreadful bit of code.
    487488
     
    492493            sage: ModularSymbols(Gamma1(17), 4).hecke_bound() # wrong!
    493494            15
    494495        """
    495         misc.verbose("WARNING: ambient.py -- hecke_bound; returning unproven guess.")
    496         return Gamma0(self.level()).sturm_bound(self.weight()) + 2*Gamma0(self.level()).dimension_eis(self.weight()) + 5
     496        if self.is_cuspidal():
     497            return Gamma0(self.level()).sturm_bound(self.weight())
     498        else:
     499            misc.verbose("WARNING: ambient.py -- hecke_bound; returning unproven guess.")
     500            return Gamma0(self.level()).sturm_bound(self.weight()) + 2*Gamma0(self.level()).dimension_eis(self.weight()) + 5
    497501
    498502    def hecke_module_of_level(self, level):
    499503        r"""
  • sage/modular/quatalg/brandt.py

    diff -r 92b42ec2270c -r 282ed7ea9245 sage/modular/quatalg/brandt.py
    a b  
    11761176            V = A.kernel()
    11771177        self.__eisenstein_subspace = V
    11781178        return V
     1179   
     1180    def is_cuspidal(self):
     1181        r"""
     1182        Returns whether self is cuspidal, i.e. has no eisenstein part.
     1183       
     1184        EXAMPLES:
     1185            sage: B = BrandtModule(3, 4)
     1186            sage: B.is_cuspidal()
     1187            False
     1188            sage: B.eisenstein_subspace()
     1189            Brandt module of dimension 1 of level 3*4 of weight 2 over Rational Field
     1190        """
     1191        return self.eisenstein_subspace().dimension() == 0
    11791192
    11801193    def monodromy_weights(self):
    11811194        r"""