Example #1
0
    def from_conjugacy_class_index_to_polynomial(self, index):
        """ A function converting from a conjugacy class index (starting at 1) to the local Euler polynomial.
            Saves a sequence of processed polynomials, obtained from the local factors table, so it can reuse computations from prime to prime
            This sequence is indexed by conjugacy class indices (starting at 1, filled with dummy first) and gives the corresponding polynomials in the form
            [coeff_deg_0, coeff_deg_1, ...], where coeff_deg_i is in ComplexField(). This could be changed later, or made parametrizable
        """
        try:
            return self._from_conjugacy_class_index_to_polynomial_fn(index)
        except AttributeError:
            local_factors = self.local_factors_table()
            field = ComplexField()
            root_of_unity = exp(
                (field.gen()) * 2 * field.pi() / int(self.character_field()))
            local_factor_processed_pols = [
                0
            ]  # dummy to account for the shift in indices
            for pol in local_factors:
                local_factor_processed_pols.append(
                    process_polynomial_over_algebraic_integer(
                        pol, field, root_of_unity))

            def tmp(conjugacy_class_index_start_1):
                return local_factor_processed_pols[
                    conjugacy_class_index_start_1]

            self._from_conjugacy_class_index_to_polynomial_fn = tmp
            return self._from_conjugacy_class_index_to_polynomial_fn(index)
Example #2
0
    def from_conjugacy_class_index_to_polynomial(self, index):
        """ A function converting from a conjugacy class index (starting at 1) to the local Euler polynomial.
            Saves a sequence of processed polynomials, obtained from the local factors table, so it can reuse computations from prime to prime
            This sequence is indexed by conjugacy class indices (starting at 1, filled with dummy first) and gives the corresponding polynomials in the form
            [coeff_deg_0, coeff_deg_1, ...], where coeff_deg_i is in ComplexField(). This could be changed later, or made parametrizable
        """
        try:
            return self._from_conjugacy_class_index_to_polynomial_fn(index)
        except AttributeError:
            local_factors = self.local_factors_table()
            field = ComplexField()
            root_of_unity = exp((field.gen()) * 2 * field.pi() / int(self.character_field()))
            local_factor_processed_pols = [0]   # dummy to account for the shift in indices
            for pol in local_factors:
                local_factor_processed_pols.append(
                    process_polynomial_over_algebraic_integer(pol, field, root_of_unity))

            def tmp(conjugacy_class_index_start_1):
                return local_factor_processed_pols[conjugacy_class_index_start_1]
            self._from_conjugacy_class_index_to_polynomial_fn = tmp
            return self._from_conjugacy_class_index_to_polynomial_fn(index)
Example #3
0
    def dimension(self,k,ignore=False, debug = 0):
        if k < 2 and not ignore:
            raise NotImplementedError("k has to >= 2")
        s = self._signature
        if not (2*k in ZZ):
            raise ValueError("k has to be integral or half-integral")
        if (2*k+s)%4 != 0 and not ignore:
            raise NotImplementedError("2k has to be congruent to -signature mod 4")
        if self._v2.has_key(0):
            v2 = self._v2[0]
        else:
            v2 = 1

        if self._g != None:
            if not self._aniso_formula:
                vals = self._g.values()
            #else:
                #print "using aniso_formula"
            M = self._g
        else:
            vals = self._M.values()
            M = self._M
            
        prec = ceil(max(log(M.order(),2),52)+1)+17
        #print prec
        RR = RealField(prec)
        CC = ComplexField(prec)
        d = self._d
        m = self._m
        if debug > 0: print d,m
            
        if self._alpha3 == None:
            if self._aniso_formula:
                self._alpha4 = 1
                self._alpha3 = -sum([BB(a)*mm for a,mm in self._v2.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 += Integer(d) - Integer(1) - self._g.beta_formula()
                #print self._alpha3, self._g.a5prime_formula()
                self._alpha3 = self._alpha3/RR(2)
            else:
                self._alpha3 = sum([(1-a)*mm for a,mm in self._v2.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 += sum([(1-a)*mm for a,mm in vals.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 = self._alpha3 / Integer(2)
                self._alpha4 = 1/Integer(2)*(vals[0]+v2) # the codimension of SkL in MkL
        alpha3 = self._alpha3
        alpha4 = self._alpha4
        if debug > 0: print alpha3, alpha4
        g1=M.char_invariant(1)
        g1=CC(g1[0]*g1[1])
        #print g1
        g2=M.char_invariant(2)
        g2=RR(real(g2[0]*g2[1]))
        if debug > 0: print g2, g2.parent()
        g3=M.char_invariant(-3)
        g3=CC(g3[0]*g3[1])
        if debug > 0: print RR(d) / RR(4), sqrt(RR(m)) / RR(4), CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8)))
        alpha1 = RR(d) / RR(4) - (sqrt(RR(m)) / RR(4)  * CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8))) * g2)
        if debug > 0: print alpha1
        alpha2 = RR(d) / RR(3) + sqrt(RR(m)) / (3 * sqrt(RR(3))) * real(exp(CC(2 * CC.pi() * CC(0,1) * (4 * k + 3 * s - 10) / 24)) * (g1+g3))
        if debug > 0: print alpha1, alpha2, g1, g2, g3, d, k, s
        dim = real(d + (d * k / Integer(12)) - alpha1 - alpha2 - alpha3)
        if debug > 0:
            print "dimension:", dim
        if abs(dim-round(dim)) > 1e-6:
            raise RuntimeError("Error ({0}) too large in dimension formula for {1} and k={2}".format(abs(dim-round(dim)), self._M if self._M is not None else self._g, k))
        dimr = dim
        dim = Integer(round(dim))
        if k >=2 and dim < 0:
            raise RuntimeError("Negative dimension (= {0}, {1})!".format(dim, dimr))
        return dim
class PicardGroup:
    def __init__(self, f, ring, verbose = False):
        """
        input: f a polynomial over a number field
        ring:  Complex Field (with some prescribed precision) where we will work over


        We represent a divisor z \in Pic**0 by a divisor in D on X
        such that z = [D - D_0] where D_0 is a fixed divisor of degree d_0
        \deg D = d_0
        
        A divisor D on X is then represented by vector space H**0(\delta - D)
        for this representation to be faithful we need \delta - D to be base point free
        for that is sufficient \deg \delta >= \deg D + 2g, 
        as we will be dealing with divisors of degree d_0 and 2d_0 we pick \delta = 3 * D_0

        a vector space H**0(-) is represented by a bases of rational functions on X
        and these functions are represented by its evaluation at an effective divisor Z

        During our computations every function will lie in H**0(3D_0) or H**0(6D_0).
        Hence, for this representation to be faithful, it is necessary and sufficient that 
        H**0({3,6}D_0 - Z) = {0}, eg \deg D_0 = 6 d_0 + 1.
        If possible \supp D_0 \cap \supp Z = empty set would be ideal.

        In summary, a vector space W will be represented with \deg Z rows and \dim columns.

        """
        self.verbose = verbose;
        assert is_CF(ring)
        self.R = ring;
        self.prec = ring.precision()
        self.f = f;
        self.a0 = list(f)[0];
        self.an = list(f)[-1];
        self.g = int(ceil( f.degree() / 2 ) - 1); 
        self.d0 = 2 * self.g + 2;
        self.extraprec = self.prec + 3 * self.d0 + 16;
        self.Rextraprec = ComplexField(self.extraprec);
        self.Rdoubleextraprec =  ComplexField(2*self.extraprec)
        self.Pi = self.Rdoubleextraprec.pi();
        self.I = self.Rdoubleextraprec(0, 1);
        self.almostzero = self.R(2)**(- self.prec * 0.7);
        self.notzero = self.R(2)**(- self.prec * 0.1);
        
        self.lower = 0; 
        

        # D_0 = (g + 1)*( \infty_{-} + \infty_{+} ) = (g + 1) * \infty

        # Pick the effective divisor Z, ie, the evaluation points
        # Pick evaluation points /!\ Weierstrass pts !
        # in theory we only need \deg Z >= 6 d_0 + 1
        # in practice we aim for >= 6 d_0 + 2
        
        
        self.nZ = 6 * self.d0 + 2;
        if self.verbose:
            print "Using %s points on the unit circle, almost uniformly spaced, to represent each function" % ( self.nZ, )
        n = self.nZ;
        n = ceil(self.nZ/2);
        Z=[]
        
        while len(Z) < self.nZ:
            # X computed in self.Rdoubleextraprec
            X = [ exp( 2 * k * self.I * self.Pi / n ) for k in range(n) ]
            Z = [];
            for i, x in enumerate(X):
                #y = (-1)**i * sqrt( f(x) )
                #Z.append( (x, y) )
                #
                # x  in self.Rdoubleextraprec !
                y =  self.Rextraprec( sqrt( self.f(x) ) )
                x =  self.Rextraprec( x )
                # making sure the points don't collide
                if y.abs() < 1e-2:
                    Z.append( (x, y) )
                else:
                    Z.append( (x, y) )
                    Z.append( (x, -y) )
            n += 1
            

        self.Z = Z;
        self.nZ = len(Z); 
        #alternatively self.Z = Z[:self.nZ], but this might lose some of the good properties of having the points uniformly on the unit circle
            
        # V represents H**0 (3 D_0)
        V = Matrix(self.Rextraprec, self.nZ, 3 * self.d0 + 1 - self.g) # \dim = 6g + 6 + 1 - g = 5 g + 7

        # Vout represents H**0(D_0)
        Vout = Matrix(self.Rextraprec, self.nZ, self.d0 + 1 - self.g) # \dim = g + 3
        
        # H**0(D_0) = <1, x, x**2, ..., x**(g + 1), y>
        # H**0(3*D_0) = <1, x, x**2, ...,x**g, x**(g + 1), y, x**(g + 2) , y x, ..., x**(g + 1 + 2g + 2), y x**(2g + 2)>, dim = 5 g + 7 = 1 + g + 2*(2*g + 3)
        

        Vexps = [None]* (3 * self.d0 + 1 - self.g)
        i = 0;
        for n in xrange( 3 * (self.g + 1) + 1):
            Vexps[i] =  [ n, 0];
            i += 1;
            if n > self.g:
                Vexps[i] = [ n - self.g - 1, 1];
                i += 1;
        
        for i, (x, y) in enumerate(self.Z):
            for j in range( 3 * self.d0 + 1 - self.g):
                V[ i, j] = x ** Vexps[j][0] * y ** Vexps[j][1]

            for j in range( self.g + 2 ):
                Vout[i,j] = x**j

            Vout[ i, self.g + 2] = y

        self.V = V;
        self.Vout = Vout;
        self.Vexps = Vexps;
        
        # W0 represents H**0 (2 D_0)
        W0 = Matrix(self.Rextraprec, self.nZ, 2 * self.d0 + 1 - self.g) 
        for i in range( self.nZ ):
            for j in range( 2 * self.d0 + 1 - self.g):
                W0[i,j] = V[i,j]
        # KV = Ker(V***) = col(V)**perp 
        KV, upper, lower = EqnMatrix(V, 3 * self.d0 + 1 - self.g);
        assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        self.lower = max(self.lower, lower)

        self.KV = KV;
        self.W0 = W0;

    def threshold_check(self, upper, lower = None):
        # checking that upper != 0, and lower ~ 0 when compared with upper
        if self.verbose:
            print "upper  = %.10e lower = %.10e" % (upper, lower)
            if lower is not None:
                print (upper >= self.notzero) and (upper*self.almostzero >= lower)
        if lower is None:
            return upper >= self.notzero
        else:
            return (upper >= self.notzero) and (upper*self.almostzero >= lower);

    def AddFlip(self, A, B):

        maxlower = self.lower;

        field = self.R;
        output_field = self.R
        if A.base_ring() == self.Rextraprec or B.base_ring() == self.Rextraprec:
            field = self.Rextraprec;
        if A.base_ring() == self.Rextraprec and B.base_ring() == self.Rextraprec:
            output_field = self.Rextraprec;
        
        # Takes H0(3D0-A), H0(3D0-B), and returns H0(3D0-C), with C s.t. A+B+C~3D0
        # H0(6D0-A-B) = H0(3D0-A) * H0(3D0-B)

        if self.verbose:
            print "PicardGroup.AddFlip(self, A, B)"
        #### STEP 1 ####
        if self.verbose:
            print "Step 1";
        
        AB = Matrix(field, self.nZ, 4 * self.d0  + 1 - self.g);    
        KAB = Matrix(field, AB.nrows() - AB.ncols(), AB.nrows());
        
        ABncols = AB.ncols();
        ABnrows = AB.nrows();
        rank = AB.ncols();
 
        while True:
            # 5 picked at random
            l = 5;
            ABtmp =  Matrix(field, self.nZ, 4 * self.d0  + 1 - self.g + l);

            for j in range(ABtmp.ncols()):
                a = random_vector_in_span(A);
                b = random_vector_in_span(B);
                for i in range(ABnrows):
                    ABtmp[i, j] = a[i] * b[i];

            Q, R, P = qrp(ABtmp, ABncols );

            upper = R[rank - 1, rank - 1].abs();
            lower = 0;
            if ABtmp.ncols() > rank and ABnrows > rank:
                lower = R[rank, rank ].abs();
            
            if self.threshold_check(upper, lower):
                # the first AB.cols columns are a basis for H0(6D0-A-B) = H0(3D0-A) * H0(3D0-B)
                # v in AB iff KAB * v = 0
                for i in range(ABnrows):
                    for j in range(ABncols):
                        AB[i, j] = Q[i, j]
                    for j in range(ABnrows - rank):
                        KAB[j, i] = Q[i, j + rank].conjugate();
                maxlower = max(maxlower, lower);
                break;
            if self.verbose:
                print "Warning: In AddFlip, not full rank at step 1, retrying."
                print "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
                


        #### STEP 2 ####
        # H0(3D0-A-B) = {s in V : s*V c H0(6D0-A-B)}

        if self.verbose:
            print "Step 2"

        #### Prec Test ####
        if self.verbose:
            a = random_vector_in_span(A);
            b = random_vector_in_span(B);
            ab = Matrix(field, self.nZ, 1);
            for i in range(self.nZ):
                ab[i, 0] = a[i] * b[i];
            print field
            print "maxlower = %s ,lower = %s " % (RealField(15)(maxlower), RealField(15)(lower))
            print "Precision of the input of MakAddflip: %s"% (RealField(15)(max(map(lambda x: RR(x[0].abs()), list(KAB * ab)))),)

        KABnrows = KAB.nrows();
        KABncols = KAB.ncols();
        while True:
            # columns =  equations for H0(3D0-A-B) = {s in V : s*V c H0(6D0-A-B)} \subset  H0(6D0-A-B)
            l = 2;
            KABred = copy(KAB);
            KABred = KABred.stack( Matrix(field, l*KABnrows, KABncols ) );

            for m in range(l): # Attempt of IGS of V
                v = random_vector_in_span( self.V )
                for j in xrange(KABncols):
                    for i in range( KABnrows ):
                        KABred[i + m * KABnrows + KABnrows , j] = KAB[i, j] * v[j]

            ABred, upper, lower = Kernel(KABred, KABred.ncols() - (self.d0 + 1 - self.g));
            if self.threshold_check(upper, lower):
                maxlower = max(maxlower, lower);
                break;
            
            if self.verbose:
                print "Warning: In AddFlip, failed IGS at step 2, retrying."
                print "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))

        
        #### STEP 3 ####
        # H0(6D0-A-B-C) = f*H0(3D0), where f in H0(30-A-B)
        if self.verbose:
            print "Step 3"

        # fv represents f*H0(3D0)
        fV= copy(self.V)
        for j in xrange(3*self.d0 + 1 - self.g):
            for i in xrange(self.nZ):
                fV[i,j] *= ABred[i,0]

        KfV, upper, lower = EqnMatrix( fV, 3 * self.d0 + 1 - self.g ) # Equations for f*V
        assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        maxlower = max(maxlower, lower);
 
        KfVnrows = KfV.nrows();
        KfVncols = KfV.ncols();

        ### STEP 4 ###
        # H0(3D0-C) = {s in V : s*H0(3D0-A-B) c H0(6D0-A-B-C)} = {s in V : s*H0(3D0-A-B) c f*V}
        if self.verbose:
            print "Step 4"
        while True:
            # Equations for H0(3D0-C)
            
            #expand KC
            l = 2;
            KC = self.KV.stack(Matrix(field, l * KfV.nrows(), self.KV.ncols()));
            KC_old_rows = self.KV.nrows();

            for m in range(l): # Attempt of IGS of H0(3D0-A-B)
                v = random_vector_in_span(ABred)
                for i in range(KfVnrows):
                    for j in range(KfVncols):
                        KC[i + m * KfVnrows + KC_old_rows, j] = v[j] * KfV[i, j];
            
            output, upper, lower = Kernel(KC, KC.ncols() - (2 * self.d0 + 1 - self.g) );
            if self.threshold_check(upper, lower):
                maxlower = max(maxlower, lower);
                break;

            if self.verbose:
                print "Warning: In MakAddFlip, failed IGS at step 4, retrying."
                print "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        
        return output.change_ring(output_field), maxlower;


    def Add(self, A, B):
        tmp, lower = self.AddFlip( A, B);
        tmp2, lower2 = self.AddFlip( tmp, self.W0);
        return tmp2, max(lower, lower2);
    
    def mDouble(self, A):
        return self.AddFlip( A, A);

    def Sub(self, A, B):
        tmp, lower =  self.AddFlip( A, self.W0)
        tmp2, lower2 =  self.AddFlip( tmp, B);
        return tmp2, max(lower, lower2);

    def Neg(self, A):
        return self.AddFlip( self.W0, A);

    def PointMinusInfinity(self, P, sign = 0):
        # Creates a divisor class of P- \inty_{(-1)**sign}
        maxlower = self.lower 
        assert self.f.degree() == 2*self.g + 2;
        sqrtan = (-1)**sign * self.Rextraprec( sqrt( self.Rdoubleextraprec(self.an)) );

        xP, yP = self.Rextraprec(P[0]),self.Rextraprec(P[1])
        assert (self.f(xP) - yP**2).abs() <= (yP**2).abs() * self.almostzero

        if xP != 0 and self.a0 != 0:
            x0 = self.Rextraprec(0);    
        else:
            x0 = xP
            while x0 == xP:
                x0 = self.Rextraprec(ZZ.random_element())
            
        y0 =  self.Rextraprec( sqrt( self.Rdoubleextraprec( self.f( x0 )))) # P0 = (x0, y0) 

        WP1 = Matrix(self.Rextraprec, self.nZ, 3 * self.g + 6) # H0(3D0 - P0 - g \infty) = H0(3D0 - P0 - g(\infty_{+} + \infty_{-}))
        EvP = Matrix(self.Rextraprec, 1, 3 * self.g + 6) # the functions of  H0(3D0-P0-g \infty) at P
        B =  Matrix(self.Rextraprec, self.nZ, 3 * self.g + 5) # H0(3D0 - \infty_{sign} - P0 - g\infty)

        # adds the functions x - x0, (x - x0)**1,  ..., (x - x0)**(2g+2) to it
        for j in xrange(2 * self.g + 2 ):
            for i, (x, y) in enumerate( self.Z ):
                WP1[ i, j] = B[ i, j] = (x - x0) ** (j + 1)
            EvP[ 0, j] = (xP - x0) ** (j + 1)
        
        # adds y - y0
        for i, (x, y) in enumerate( self.Z ):
            WP1[ i, 2 * self.g + 2 ] = B[ i, 2 * self.g + 2] = y - y0
        EvP[ 0, 2 * self.g + 2] = yP - y0

        # adds (x - x0) * y ... (x-x0)**(g+1)*y
        for j in range(1, self.g + 2):
            for i, (x,y) in enumerate( self.Z ):
                WP1[ i, 2 * self.g + 2 + j ] = B[ i, 2 * self.g + 2 + j] = (x-x0)**j * y 
            EvP[ 0, 2 * self.g + 2 + j] = (xP - x0)**j * yP


        # adds (x - x0)**(2g + 3) and  y *  (x - x0)**(g + 2)
        for i,(x,y) in enumerate(self.Z):
            WP1[ i, 3 * self.g + 4 ] =  (x - x0)**( 2 * self.g + 3)
            WP1[ i, 3 * self.g + 5 ] = y *  (x - x0)**(self.g + 2)
            B[ i, 3 * self.g + 4 ] =  (x - x0)**( self.g + 2) * ( y - sqrtan * x**(self.g + 1) )

        EvP[ 0, 3 * self.g + 4] = (xP - x0) ** ( 2 * self.g + 3)
        EvP[ 0, 3 * self.g + 5] = yP * (xP - x0)**(self.g + 2)
        
        # A = functions in  H0(3D0-P0-g \infty) that vanish at P
        # = H**0(3D0 - P0 - P -g \infty)
        K, upper, lower = Kernel(EvP, EvP.ncols() - (3 * self.g + 5))
        assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        maxlower = max(maxlower, lower);

        A = WP1 * K
        # A - B = P0 + P + g \infty - (\infty_{+} + P0 + g\infty) = P - \inty_{+}
        res, lower = self.Sub(A,B)
        maxlower = max(maxlower, lower);
        return res.change_ring(self.R), maxlower;
    
    def TwoPointsMinusInfinity(self, P, Q): # Creates a divisor class of P + Q - g*\infty
        maxlower = self.lower
        xP, yP = self.Rextraprec(P[0]), self.Rextraprec(P[1])
        xQ, yQ = self.Rextraprec(Q[0]), self.Rextraprec(Q[1])

        assert (self.f(xP) - yP**2).abs() <= (yP**2).abs() * self.almostzero
        assert (self.f(xQ) - yQ**2).abs() <= (yQ**2).abs() * self.almostzero

        WPQ = Matrix(self.Rextraprec, self.nZ, 3 * self.g + 7) # H0(3D0  - g*\infty)
        Ev = Matrix(self.Rextraprec, 2, 3 * self.g + 7) # basis of  H0(3D0  - g*\infty) evaluated at P and Q
        Exps=[]
        for n in range( 2 * self.g + 4):
            Exps.append((n,0))
            if n > self.g:
                Exps.append(( n - self.g - 1, 1))

        for j in range( 3 * self.g + 7):
            u, v = Exps[j]
            for i in range( self.nZ ):
                x, y = self.Z[i]
                WPQ[ i, j ] = x**u * y**v

            Ev[0,j] = xP**u * yP**v
            Ev[1,j] = xQ**u * yQ**v
        
        K, upper, lower = Kernel(Ev, 2)
        assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        maxlower = max(maxlower, lower);
        #Returns H0(3*D0 - P - Q - g infty)
        # note that  [P + Q + g infty - D0] ~ P + Q - infty
        return (WPQ * K).change_ring(self.R), maxlower


    def linearequations(self, W):
        maxlower = self.lower
        # From W = H0( 3*D0 - D ), return H0((g + 1)*\infty - E), where E is effective of degree g s.t. E - (g/2) * \infty + D-(g+1)\infty ~ 0. /!\ Assumes g even /!\
        # E0 = (3g/2+2)\infty = E + D + \infty
        # H0(3D0 - D - E0) = W( - E0) = {w in W : w*x**(3g/2+2) in W} has dim >= 1
        # phi \in W(-E0)  
        # <=>  div phi + 3D0 - D - E0  >= 0
        # <=>  div phi + 3D0 - D - E0 = E effective
        # <=> div phi = E + D - (3g/2 + 1)\infty
        assert self.g % 2 == 0, "the genus must be even for this implementation to work";

        KW, upper, lower = EqnMatrix(W.change_ring(self.Rextraprec), 2 * self.d0 + 1 - self.g);
        assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower));
        maxlower = max(maxlower, lower);

        KWnrows = KW.nrows();
        KWncols = KW.ncols();


        K = KW.stack(Matrix(self.Rextraprec, KWnrows, KWncols));

        for j, (x, y) in enumerate(self.Z):
            xpower =  x**( 3 * self.g/2 + 2);
            for i in range(KWnrows):
                K[i + KWnrows,j] = KW[i,j] * xpower;

        phi, upper, lower = Kernel(K, KWncols - 1);
        # rank >= 1
        if self.verbose:
            print "phi upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))    
        assert self.threshold_check(1,lower), "upper = %s lower = %s" % (RealField(35)(1), RealField(35)(lower))
        maxlower = max(maxlower, lower);

        # phi*H0( (5g/2+3) \infty) = H0( (4g + 4) \infty - D - E)
        Exps=[]

        for i in range( 5 * self.g / 2 + 4 ):
            Exps.append((i,0))
            if i > self.g:
                Exps.append(( i - self.g - 1, 1))
        
        # H0((4g+4)\infty-D-E)
        H4 = Matrix(self.Rextraprec, self.nZ, 4 * self.g + 7)

        for j, (u,v) in enumerate(Exps):
            for i, (x, y) in enumerate(self.Z):
                H4[i,j] = phi[i, 0] * x**u * y**v
        


        K4, upper, lower = EqnMatrix(H4, 4 * self.g + 7 )
        assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        maxlower = max(maxlower, lower);


        # H0((g+1)\infty - E) = {s in V : s*W c H0((4g+4)OO-D-E)}
        # \dim >= 3 = self.d0 + 1 - 2 * self.g (equality holds for g <= 3)
        if self.g >= 4:
            print "Warning: Riemann--Roch correction term ignored when computing \dim H**0((g+1)\infty - E)!!!"
        K4nrows = K4.nrows();
        K4ncols = K4.ncols();
        while True:
            l = 2;
            Kres = copy(self.KV);
            Kres_old_rows = Kres.nrows();
            Kres = Kres.stack(Matrix(self.R, l * K4nrows, K4ncols));
            
            for m in range(l): # Attempt of IGS of W
                v=random_vector_in_span(W)
                for i in range(K4nrows):
                    for j in range(K4ncols):
                        Kres[i + m*K4nrows + Kres_old_rows, j] = v[j] * K4[i, j]
            
            res, upper, lower = Kernel(Kres, Kres.ncols() - (self.d0 + 1 - 2 * self.g));
            if self.threshold_check(upper, lower):
                maxlower = max(maxlower, lower);
                break;
            
            if self.verbose:
                print "Warning: In MakOutput, failed IGS at step 3, retrying."
                print "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        

        

        # Expressing H0((g+1)\infty-E) in terms of H0(D0)

        S = Matrix(self.R, self.nZ, (self.g + 3) + (self.d0 + 1 - 2 * self.g) )
        for i in range( self.nZ ):
            for j in range( self.g + 3):
                S[i,j] = self.Vout[i,j]

            for j in range( self.d0 + 1 - 2 * self.g):
                S[i ,j + self.g + 3] = res[i,  j ]

        K, upper, lower = Kernel(S, S.ncols() - ( self.d0 + 1 - 2 * self.g)) # S.cols - 3
        assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        maxlower = max(maxlower, lower);
        
        # dropping the last  (self.d0 + 1 - 2 * self.g)  rows
        # K.rows = self.g + 3 
        out = K.matrix_from_rows([i for i in range(self.g + 3)])
        # a basis in H**0( D_0) for H**0((g+1)\infty - E)
        return out, maxlower
#
#        # Expressing H0((g+1)\infty-E) in terms of H0(3*D0)
#        # we could make have it in terms of H0(D0), however the extra rows are helpful for sanity checks
#
#        S = Matrix(self.R, self.nZ, (5*self.g + 7) + (self.d0 + 1 - 2 * self.g) )
#        for i in range( self.nZ ):
#            for j in range( 5*self.g + 7):
#                S[i,j] = self.V[i,j]
#
#            for j in range( self.d0 + 1 - 2 * self.g):
#                S[i ,j + 5*self.g + 7] = res[i,  j ]
#
#        K, upper, lower = Kernel(S, S.ncols() - ( self.d0 + 1 - 2 * self.g)) # S.cols - 3
#        assert self.threshold_check(upper, lower), "upper = %.10e lower = %.10e" % (upper, lower)
#
#        # dropping the last  (self.d0 + 1 - 2 * self.g)  rows
#        out = K.matrix_from_rows([i for i in range(5*self.g + 7)])
#        # K.rows = 5*self.g + 7
#        # a basis of  H**0((g+1)\infty - E) in terms of the basis elements of H**0( 3*D_0)
#        return out
    
    def support(self, basis):
        # Input:  a basis in H**0( D_0) for H**0((g+1)\infty - E), where E is an effective divisor of degree g/2
        # Output: returns the support of E as a list of g points 
 
        # Computing the intersection of 
        # <1, x, x**2,..., x**g> with <basis>
        B = basis.augment( identity_matrix(self.g + 1).stack(Matrix(basis.nrows() - (self.g + 1), (self.g + 1))))
        KB, upper, lower  = Kernel(B, basis.ncols() + self.g )
        if self.verbose:
            print "KB upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        maxlower = self.lower
        
        result = [None for _ in range(self.g)]
        
        # if dim of the intersection of <1, x, x**2,..., x**g> with <basis> is 1
        if self.threshold_check(upper, lower):
            # we have the expected rank, all the roots are simple, unless E = 2*P
            # as in genus = 2 we can't have E = tau(P) + P
            maxlower = max(maxlower, lower);

            Rw = PolynomialRing(self.Rdoubleextraprec, "T")
            poly = Rw( KB.column(0)[-(self.g + 1):].list() )
            
            if self.g == 2:
                a, b, c = list(poly)
                disc = (b**2 - 4*a*c).abs()
                #a2 = (a**2).abs()
                dpoly = poly.derivative()
                if self.threshold_check((a**2).abs(), disc):
                    xcoordinates = dpoly.complex_roots() + dpoly.complex_roots()
                    maxlower = max(maxlower, disc);
                else:
                    xcoordinates = poly.complex_roots()
            else:
                xcoordinates = poly.complex_roots()

            for i, x in enumerate(xcoordinates):
                    y0 = self.Rextraprec(sqrt(self.f(x)));
                    x0 = self.Rextraprec(x)
                    vp = vector(self.R, [x0**u * y0**v for u, v in self.Vexps[:basis.nrows()] ]);
                    vn = vector(self.R, [x0**u * (-y0)**v for u, v in self.Vexps[:basis.nrows()] ]);
                    np = norm( vp * basis);
                    nn = norm( vn * basis);
                    #is it a simple root?
                    if dpoly(x).abs() < self.notzero:
                        assert self.g == 2, "one needs to be extra careful for genus > 2" 
                        
                    if self.threshold_check(np, nn) and not self.threshold_check(nn, np): #np > nn ~ 0
                        result[i] = (x0, -y0);
                        maxlower = max(maxlower, nn);
                    elif  not self.threshold_check(np, nn) and self.threshold_check(nn, np): #nn > np ~ 0
                        result[i] = (x0, y0);
                        maxlower = max(maxlower, np);

                    else:
                        print "sign for y is not clear: neg = %s, pos = %s,\ny = %s + %s * I = 0?" % tuple(vector(RealField(15), (nn, np, y0.real(), y0.imag())));
                        if nn > np:
                            result[i] = (x0, y0);
                            maxlower = max(maxlower, np);

                        else:
                            result[i] = (x0, -y0);
                            maxlower = max(maxlower, nn);

#                    else:
#                        assert self.g == 2, "for now only genus 2"
#                        # for g = 2,  we can't have E = P + tau(P), as (x - x0) \in H**0((g+1)\infty - E)
#                        # thus the rank of B should be at most  basis.ncols() + 1
#                        for j, xj in enumerate(xcoordinates[i+1:]):
#                            if (x0 - xj).abs() < self.notzero:
#                                # we might have a double root, and at the moment this should only work for g == 2
#                                break;
#                        #j is the other root 
#                        if self.threshold_check(np, nn) and not self.threshold_check(nn, np):
#                            result[j] = result[i] = (x0, -y0);
#                        elif not self.threshold_check(np, nn) and self.threshold_check(nn, np):
#                            result[j] = result[i] = (x0, y0);
#                        else:
#                            #this covers the case that y0 ~ 0
#                            if self.f(x0) > self.almostzero:
#                                print "sign for y is not clear: neg = %.2e, pos = %.2e,\nassuming y = %.2e + %.2e * I = 0" % (nn, np, y0.real(), y0.imag());
#                            result[j] = result[i] = (x0, 0);
#                    
#                                
            return result, maxlower;
        else:
            if self.verbose:
                print "there is at least a root at infinity, i.e. \inf_{+,-} \in supp E"
                print (RealField(35)(upper), RealField(35)(lower))
            # there is at least a root at infinity, i.e. \inf_{+,-} \in supp E
            # recall that \inf_{+} + \inf_{-} ~ P + tau(P), and in this case we have booth roots at infinity 
            assert self.g == 2, "for now only genus 2"


            Ebasis, upper, lower = EqnMatrix(basis,  basis.ncols() )
            assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
            maxlower = max(maxlower, lower);

            B = basis.augment( identity_matrix(self.g ).stack(Matrix(basis.nrows() - (self.g ), (self.g ))))
            KB, upper, lower  = Kernel(B, basis.ncols() + self.g - 1 )

            # 1 \in <basis>
            v0 = vector(self.R, [0] * basis.nrows())
            v0[0] = 1
            norm_one = norm(Ebasis * v0)
      
            if not self.threshold_check(upper, lower):
                # dim <1, x> cap <basis> = 2

                #1 \in <basis>
                assert self.threshold_check(1, norm_one),  "upper = %s lower = %s norm_one = %s " % (RealField(35)(upper), RealField(35)(lower), RealField(35)(norm_one));
                maxlower = max(maxlower, norm_one);
                
                #x \in <basis>

                vx = vector(self.R, [0]*basis.nrows())
                vx[1] = 1
                lower = norm(Ebasis * vx)
                assert self.threshold_check(1, lower), "lower = %s" % (RealField(35)(lower),);
                maxlower = max(maxlower, lower);
                
                vx2 = vector(self.R, [0]*basis.nrows())
                vx2[2] = 1
                lower = norm(Ebasis * vx2)
                if self.threshold_check(1, lower):
                    # E = \inf_{+} + \inf_{-} 
                    # <1, x, x^2>  \in H**0((g+1)\infty - E)
                    # x \in H^0 => 0 + 2 \infty - E >= 0
                    # x^2 \in H^0 => 4 * P_0 + \infty - E >= 0 for all P0

                    maxlower = max(maxlower, lower);
                    return [+Infinity, -Infinity], maxlower

                # <1, x>  \in H**0((g+1)\infty - E)
                # but not x^2
                # supp(E) \subsetneq { \inf_{+}, \inf_{-}  }
                if self.f.degree() % 2 == 0:
                    # we need to figure out the sign at infinity
                    Maug = Matrix(basis.nrows() - self.g - 1, self.g + 1).stack(identity_matrix(self.g + 1))
                    B = basis.augment( Maug )
                    KB, upper, lower  = Kernel(B, basis.ncols() + self.g )

                    a, b, c = KB.column(0)[-(2 + 1):].list()
                    assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))

                    tmp = (-b/c) / sqrt(self.f.list()[-1]);
                    assert self.threshold_check( tmp.real(), tmp.imag()), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
                    infsign = round(tmp.real());
                    assert infsign in [1, -1]


                    return [infsign*Infinity, infsign*Infinity], maxlower


                return [+Infinity, +Infinity], maxlower
            else:
                maxlower = max(maxlower, lower);
                #1 \notin <basis>
                assert self.threshold_check(norm_one),  "upper = %s lower = %s norm_one = %s " % (RealField(35)(upper), RealField(35)(lower), RealField(35)(norm_one));
                        
                        
            Rw = PolynomialRing(self.Rdoubleextraprec, "T")
            xcoordinates = Rw(KB.column(0)[-(self.g):].list()).complex_roots()
            assert len(xcoordinates) == 1;
            x0 = xcoordinates[0];
            y0 = self.Rextraprec(sqrt(self.f(x0)));

                        
            
            # if dim <1, x, x**2> cap <basis> >= 2
            # then dim <1, x> cap <basis> >= 1

            
            
            
            # we must have <1, x> \subset <basis>

            # double check that (x - x0) and (x - x0)**2 are in <basis>
            
            # (x - x0)
            v1 = vector(self.R, [0]*basis.nrows())
            v1[0] = -x0
            v1[1] = 1
            lower = norm(Ebasis * v1)
            assert self.threshold_check(1, lower), "lower = %s" % (RealField(35)(lower),);
            maxlower = max(maxlower, lower);

            # (x - x0)**2
            v2 = vector(self.R, [0]*basis.nrows())
            v2[0] = x0**2
            v2[1] = - 2*x0
            v2[2] = 1
            lower = norm(Ebasis * v2)
            assert self.threshold_check(1, lower), "lower = %s" % (RealField(35)(lower),);

            maxlower = max(maxlower, lower);

            
            # (x - x0)**3
            v3 = vector(self.R, [0]*basis.nrows())
            v3[0] = -x0**3
            v3[1] = 3*x0**2
            v3[2] = -3*x0
            v3[3] = 1
            nc = norm(Ebasis * v3)
            
            
            vp = vector(self.R, [x0**i * y0**j for i,j in self.Vexps[:basis.nrows()]]);
            vn = vector(self.R, [x0**i * (-y0)**j for i,j in self.Vexps[:basis.nrows()]]);

            np = norm( vp * basis);
            nn = norm( vn * basis);
            

            # either E = P + \inf_{+/-} 
            # or E = P + tau(P)   with P != \inf_{*}, but in this case E ~ \inf_+ + \inf_-        

            if self.threshold_check(np, nn) and not self.threshold_check(nn, np): #np > nn ~ 0
                result[0] = (x0, -y0);
                maxlower = max(maxlower, nn);

            elif not self.threshold_check(np, nn) and self.threshold_check(nn, np): #nn > np ~ 0
                result[0]  = (x0, y0);
                maxlower = max(maxlower, np);

            else:
                if self.threshold_check(1,nc) and self.threshold_check(1,np) and self.threshold_check(1,nn):
                    result[0] = (x0, y0)
                    result[1] = (x0, -y0)
                    maxlower = max(maxlower, nc, np, nn);
                    # this is equivalent to:  return result, maxlower
                    return [+Infinity, -Infinity], maxlower
                if self.f(x0) > self.almostzero :
                    print "sign for y is not clear: neg = %s, pos = %s,\nassuming y = %s + %s * I = 0" % tuple( vector( RealField(15), (nn, np, y0.real(), y0.imag())));
                result[0] = (x0, 0);
            
            # E = P + \inf_{+/-} 
            # P = result[0]
            x0, y0 = result[0]



            # Now figure out what infinity is in the supp of E
            # by checking if   y - s*x**(g+1) - (y0 - s*x0**(g+1)) \in <basis>
            # for s = sign * sqrt(an)
            sqrtan =  self.Rextraprec( sqrt( self.an) );
            # vp -> no pole at inf_{+} -> inf_{+} \in supp E
            vp = vector(self.R, [0]*basis.nrows())
            # vn -> no pole at inf_{-} -> inf_{-} \in supp E
            vn = vector(self.R, [0]*basis.nrows())
            vp[0] = -(y0 - sqrtan*x0**(self.g + 1))
            vn[0] = -(y0 + sqrtan*x0**(self.g + 1))
            vp[self.g + 1] = -sqrtan
            vn[self.g + 1] = sqrtan
            vp[self.g + 2] = 1
            vn[self.g + 2] = 1
            
            np = norm( Ebasis * vp );
            nn = norm( Ebasis * vn );

            


            if self.threshold_check(np * nc, nn) and not self.threshold_check(nn * nc, np) and not self.threshold_check(nn * np, nc): #np * nc > nn ~ 0
                maxlower = max(maxlower, nn);
                result[1] = -Infinity ;
            elif not self.threshold_check(np * nc, nn) and self.threshold_check(nn * nc, np) and not self.threshold_check(nn * np, nc): #nn * nc > np ~ 0
                maxlower = max(maxlower, np);
                result[1] = +Infinity
            elif not self.threshold_check(np * nc, nn) and not self.threshold_check(nn * nc, np) and self.threshold_check(nn * np, nc): # np*nn > nc
                # this should have been rulled out before, but now it looks more likely to have P + tau(P)
                # instead of E = P + inf
                maxlower = max(maxlower, nc);
                #this is equivalent to: result[1] = (x0, -y0)
                result = [+Infinity, -Infinity]
            else:
                print "inf_{?} \in supp E not clear: neg = %s, pos = %s, conj = %s" % tuple(vector(RealField(15),(nn, np, nc)));
                mn = min(nn, np, nc)
                maxlower = max(maxlower, mn);
                if np == mn:
                    result[1] = +Infinity;
                elif nn == mn:
                    result[1] = -Infinity;
                elif nc == mn:
                    #this is equivalent to: result[1] = (x0, -y0)
                    result = [+Infinity, -Infinity]
                else:
                    assert False, "something went wrong"
            return result, maxlower
Example #5
0
    def dimension(self, k, ignore=False, debug=0):
        if k < 2 and not ignore:
            raise NotImplementedError("k has to >= 2")
        s = self._signature
        if not (2 * k in ZZ):
            raise ValueError("k has to be integral or half-integral")
        if (2 * k + s) % 4 != 0 and not ignore:
            raise NotImplementedError(
                "2k has to be congruent to -signature mod 4")
        if self._v2.has_key(0):
            v2 = self._v2[0]
        else:
            v2 = 1

        if self._g != None:
            if not self._aniso_formula:
                vals = self._g.values()
            #else:
            #print "using aniso_formula"
            M = self._g
        else:
            vals = self._M.values()
            M = self._M

        prec = ceil(max(log(M.order(), 2), 52) + 1) + 17
        #print prec
        RR = RealField(prec)
        CC = ComplexField(prec)
        d = self._d
        m = self._m
        if debug > 0: print d, m

        if self._alpha3 == None:
            if self._aniso_formula:
                self._alpha4 = 1
                self._alpha3 = -sum(
                    [BB(a) * mm for a, mm in self._v2.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 += Integer(d) - Integer(
                    1) - self._g.beta_formula()
                #print self._alpha3, self._g.a5prime_formula()
                self._alpha3 = self._alpha3 / RR(2)
            else:
                self._alpha3 = sum([(1 - a) * mm
                                    for a, mm in self._v2.iteritems()
                                    if a != 0])
                #print self._alpha3
                self._alpha3 += sum([(1 - a) * mm
                                     for a, mm in vals.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 = self._alpha3 / Integer(2)
                self._alpha4 = 1 / Integer(2) * (
                    vals[0] + v2)  # the codimension of SkL in MkL
        alpha3 = self._alpha3
        alpha4 = self._alpha4
        if debug > 0: print alpha3, alpha4
        g1 = M.char_invariant(1)
        g1 = CC(g1[0] * g1[1])
        #print g1
        g2 = M.char_invariant(2)
        g2 = RR(real(g2[0] * g2[1]))
        if debug > 0: print g2, g2.parent()
        g3 = M.char_invariant(-3)
        g3 = CC(g3[0] * g3[1])
        if debug > 0:
            print RR(d) / RR(4), sqrt(RR(m)) / RR(4), CC(
                exp(2 * CC.pi() * CC(0, 1) * (2 * k + s) / Integer(8)))
        alpha1 = RR(d) / RR(4) - (sqrt(RR(m)) / RR(4) * CC(
            exp(2 * CC.pi() * CC(0, 1) * (2 * k + s) / Integer(8))) * g2)
        if debug > 0: print alpha1
        alpha2 = RR(d) / RR(3) + sqrt(RR(m)) / (3 * sqrt(RR(3))) * real(
            exp(CC(2 * CC.pi() * CC(0, 1) * (4 * k + 3 * s - 10) / 24)) *
            (g1 + g3))
        if debug > 0: print alpha1, alpha2, g1, g2, g3, d, k, s
        dim = real(d + (d * k / Integer(12)) - alpha1 - alpha2 - alpha3)
        if debug > 0:
            print "dimension:", dim
        if abs(dim - round(dim)) > 1e-6:
            raise RuntimeError(
                "Error ({0}) too large in dimension formula for {1} and k={2}".
                format(abs(dim - round(dim)),
                       self._M if self._M is not None else self._g, k))
        dimr = dim
        dim = Integer(round(dim))
        if k >= 2 and dim < 0:
            raise RuntimeError("Negative dimension (= {0}, {1})!".format(
                dim, dimr))
        return dim
Example #6
0
    def dimension(self, k, ignore=False, debug=0):
        if k < 2 and not ignore:
            raise NotImplementedError("k has to >= 2")
        s = self._signature
        if not (2 * k in ZZ):
            raise ValueError("k has to be integral or half-integral")
        if (2 * k + s) % 2 != 0:
            return 0
        m = self._m
        n2 = self._n2
        if self._v2.has_key(0):
            v2 = self._v2[0]
        else:
            v2 = 1

        if self._g != None:
            if not self._aniso_formula:
                vals = self._g.values()
            #else:
            #print "using aniso_formula"
            M = self._g
        else:
            vals = self._M.values()
            M = self._M

        if (2 * k + s) % 4 == 0:
            d = Integer(1) / Integer(2) * (
                m + n2
            )  # |dimension of the Weil representation on even functions|
            self._d = d
            self._alpha4 = 1 / Integer(2) * (vals[0] + v2
                                             )  # the codimension of SkL in MkL
        else:
            d = Integer(1) / Integer(2) * (
                m - n2
            )  # |dimension of the Weil representation on odd functions|
            self._d = d
            self._alpha4 = 1 / Integer(2) * (vals[0] - v2
                                             )  # the codimension of SkL in MkL

        prec = ceil(max(log(M.order(), 2), 52) + 1) + 17
        #print prec
        RR = RealField(prec)
        CC = ComplexField(prec)

        if debug > 0: print "d, m = {0}, {1}".format(d, m)
        eps = exp(2 * CC.pi() * CC(0, 1) * (s + 2 * k) / Integer(4))
        eps = round(real(eps))
        if self._alpha3 is None or self._last_eps != eps:
            self._last_eps = eps
            if self._aniso_formula:
                self._alpha4 = 1
                self._alpha3 = -sum(
                    [BB(a) * mm for a, mm in self._v2.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 += Integer(d) - Integer(
                    1) - self._g.beta_formula()
                #print self._alpha3, self._g.a5prime_formula()
                self._alpha3 = self._alpha3 / RR(2)
            else:
                self._alpha3 = eps * sum(
                    [(1 - a) * mm for a, mm in self._v2.iteritems() if a != 0])
                if debug > 0: print "alpha3t = ", self._alpha3
                self._alpha3 += sum([(1 - a) * mm
                                     for a, mm in vals.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 = self._alpha3 / Integer(2)
        alpha3 = self._alpha3
        alpha4 = self._alpha4
        if debug > 0: print alpha3, alpha4
        g1 = M.char_invariant(1)
        g1 = CC(g1[0] * g1[1])
        #print g1
        g2 = M.char_invariant(2)
        g2 = CC(g2[0] * g2[1])
        if debug > 0: print g2, g2.parent()
        g3 = M.char_invariant(-3)
        g3 = CC(g3[0] * g3[1])
        if debug > 0: print "eps = {0}".format(eps)
        if debug > 0:
            print "d/4 = {0}, m/4 = {1}, e^(2pi i (2k+s)/8) = {2}".format(
                RR(d) / RR(4),
                sqrt(RR(m)) / RR(4),
                CC(exp(2 * CC.pi() * CC(0, 1) * (2 * k + s) / Integer(8))))
        if eps == 1:
            g2_2 = real(g2)
        else:
            g2_2 = imag(g2) * CC(0, 1)
        alpha1 = RR(d) / RR(4) - sqrt(RR(m)) / RR(4) * CC(
            exp(2 * CC.pi() * CC(0, 1) * (2 * k + s) / Integer(8)) * g2_2)
        if debug > 0: print alpha1
        alpha2 = RR(d) / RR(3) + sqrt(RR(m)) / (3 * sqrt(RR(3))) * real(
            exp(CC(2 * CC.pi() * CC(0, 1) * (4 * k + 3 * s - 10) / 24)) *
            (g1 + eps * g3))
        if debug > 0:
            print "alpha1 = {0}, alpha2 = {1}, alpha3 = {2}, g1 = {3}, g2 = {4}, g3 = {5}, d = {6}, k = {7}, s = {8}".format(
                alpha1, alpha2, alpha3, g1, g2, g3, d, k, s)
        dim = real(d + (d * k / Integer(12)) - alpha1 - alpha2 - alpha3)
        if debug > 0:
            print "dimension:", dim
        if abs(dim - round(dim)) > 1e-6:
            raise RuntimeError(
                "Error ({0}) too large in dimension formula for {1} and k={2}".
                format(abs(dim - round(dim)),
                       self._M if self._M is not None else self._g, k))
        dimr = dim
        dim = Integer(round(dim))
        if k >= 2 and dim < 0:
            raise RuntimeError("Negative dimension (= {0}, {1})!".format(
                dim, dimr))
        return dim
Example #7
0
    def dimension(self,k,ignore=False, debug = 0):
        if k < 2 and not ignore:
            raise NotImplementedError("k has to >= 2")
        s = self._signature
        if not (2*k in ZZ):
            raise ValueError("k has to be integral or half-integral")
        if (2*k+s)%2 != 0:
            return 0
        m = self._m
        n2 = self._n2
        if self._v2.has_key(0):
            v2 = self._v2[0]
        else:
            v2 = 1

        if self._g != None:
            if not self._aniso_formula:
                vals = self._g.values()
            #else:
                #print "using aniso_formula"
            M = self._g
        else:
            vals = self._M.values()
            M = self._M

        if (2*k+s)%4 == 0:
            d = Integer(1)/Integer(2)*(m+n2) # |dimension of the Weil representation on even functions|
            self._d = d
            self._alpha4 = 1/Integer(2)*(vals[0]+v2) # the codimension of SkL in MkL
        else:
            d = Integer(1)/Integer(2)*(m-n2) # |dimension of the Weil representation on odd functions|
            self._d = d
            self._alpha4 = 1/Integer(2)*(vals[0]-v2) # the codimension of SkL in MkL
            
        prec = ceil(max(log(M.order(),2),52)+1)+17
        #print prec
        RR = RealField(prec)
        CC = ComplexField(prec)
        
        if debug > 0: print "d, m = {0}, {1}".format(d,m)
        eps = exp( 2 * CC.pi() * CC(0,1) * (s + 2*k) / Integer(4) )
        eps = round(real(eps))        
        if self._alpha3 is None or self._last_eps != eps:
            self._last_eps = eps
            if self._aniso_formula:
                self._alpha4 = 1
                self._alpha3 = -sum([BB(a)*mm for a,mm in self._v2.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 += Integer(d) - Integer(1) - self._g.beta_formula()
                #print self._alpha3, self._g.a5prime_formula()
                self._alpha3 = self._alpha3/RR(2)
            else:
                self._alpha3 = eps*sum([(1-a)*mm for a,mm in self._v2.iteritems() if a != 0])
                if debug>0: print "alpha3t = ", self._alpha3
                self._alpha3 += sum([(1-a)*mm for a,mm in vals.iteritems() if a != 0])
                #print self._alpha3
                self._alpha3 = self._alpha3 / Integer(2)
        alpha3 = self._alpha3
        alpha4 = self._alpha4
        if debug > 0: print alpha3, alpha4
        g1=M.char_invariant(1)
        g1=CC(g1[0]*g1[1])
        #print g1
        g2=M.char_invariant(2)
        g2=CC(g2[0]*g2[1])
        if debug > 0: print g2, g2.parent()
        g3=M.char_invariant(-3)
        g3=CC(g3[0]*g3[1])
        if debug > 0: print "eps = {0}".format(eps)
        if debug > 0: print "d/4 = {0}, m/4 = {1}, e^(2pi i (2k+s)/8) = {2}".format(RR(d) / RR(4), sqrt(RR(m)) / RR(4), CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8))))
        if eps == 1:
            g2_2 = real(g2)
        else:
            g2_2 = imag(g2)*CC(0,1)
        alpha1 = RR(d) / RR(4) - sqrt(RR(m)) / RR(4)  * CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8)) * g2_2)
        if debug > 0: print alpha1
        alpha2 = RR(d) / RR(3) + sqrt(RR(m)) / (3 * sqrt(RR(3))) * real(exp(CC(2 * CC.pi() * CC(0,1) * (4 * k + 3 * s - 10) / 24)) * (g1 + eps*g3))
        if debug > 0: print "alpha1 = {0}, alpha2 = {1}, alpha3 = {2}, g1 = {3}, g2 = {4}, g3 = {5}, d = {6}, k = {7}, s = {8}".format(alpha1, alpha2, alpha3, g1, g2, g3, d, k, s)
        dim = real(d + (d * k / Integer(12)) - alpha1 - alpha2 - alpha3)
        if debug > 0:
            print "dimension:", dim
        if abs(dim-round(dim)) > 1e-6:
            raise RuntimeError("Error ({0}) too large in dimension formula for {1} and k={2}".format(abs(dim-round(dim)), self._M if self._M is not None else self._g, k))
        dimr = dim
        dim = Integer(round(dim))
        if k >=2 and dim < 0:
            raise RuntimeError("Negative dimension (= {0}, {1})!".format(dim, dimr))
        return dim