Exemple #1
0
    def init_tensor_product(self, V, W):
        """
        We are given two Galois representations and we
        will return their tensor product.
        """
        self.original_object = V.original_object + W.original_object
        self.object_type = "tensorproduct"
        self.V1 = V
        self.V2 = W
        self.dim = V.dim * W.dim
        self.motivic_weight = V.motivic_weight + W.motivic_weight
        self.langlands = False  # status 2014 :)
        self.besancon_bound = min(V.besancon_bound, W.besancon_bound)

        bad2 = ZZ(W.conductor).prime_factors()
        bad_primes = [x for x in ZZ(V.conductor).prime_factors() if x in bad2]
        for p in bad_primes:
            if (p not in V.bad_semistable_primes
                    and p not in W.bad_semistable_primes):
                # this condition above only applies to the current type of objects
                # for general reps we would have to test the lines below
                # to be certain that the formulae are correct.
                #if ((p not in V.bad_semistable_primes or p not in W.bad_pot_good) and
                #(p not in W.bad_semistable_primes or p not in V.bad_pot_good) and
                #(p not in V.bad_semistable_primes or p not in W.bad_semistable_primes)):
                raise NotImplementedError(
                    "Currently tensor products of Galois representations are only implemented under some conditions.",
                    "The behaviour at %d is too wild (both factors must be semistable)."
                    % p)

        # check for the possibily of getting poles
        if V.weight == W.weight and V.conductor == W.conductor:
            Vans = V.algebraic_coefficients(50)
            Wans = W.algebraic_coefficients(50)
            CC = ComplexField()
            if ((Vans[2] in ZZ and Wans[2] in ZZ
                 and all(Vans[n] == Wans[n] for n in range(1, 50)))
                    or all(CC(Vans[n]) == CC(Wans[n]) for n in range(1, 50))):
                raise NotImplementedError(
                    "It seems you are asking to tensor a " +
                    "Galois representation with its dual " +
                    "which results in the L-function having " +
                    "a pole. This is not implemented here.")

        scommon = [
            x for x in V.bad_semistable_primes if x in W.bad_semistable_primes
        ]

        N = W.conductor**V.dim
        N *= V.conductor**W.dim
        for p in bad_primes:
            n1_tame = V.dim - V.local_euler_factor(p).degree()
            n2_tame = W.dim - W.local_euler_factor(p).degree()
            nn = n1_tame * n2_tame
            N = N // p**nn
            if p in scommon:  # both are degree 1 in this case
                N = N // p
        self.conductor = N

        h1 = selberg_to_hodge(V.motivic_weight, V.mu_fe, V.nu_fe)
        h2 = selberg_to_hodge(W.motivic_weight, W.mu_fe, W.nu_fe)
        h = tensor_hodge(h1, h2)
        w, m, n = hodge_to_selberg(h)
        self.mu_fe = m
        self.nu_fe = n
        _, self.gammaV = gamma_factors(h)

        # this is used in getting the Dirichlet coefficients.
        self.bad_primes_info = []
        for p in bad_primes:
            # we have to check if this works in all bad cases !
            f1 = V.local_euler_factor(p)
            f2 = W.local_euler_factor(p)
            # might be dodgy if f1 or f2 is an approx to the Euler factor
            if p in scommon:
                E = tensor_local_factors(f1, f2, V.dim * W.dim)
                T = f1.parent().gens()[0]  # right answer is E(T)*E(pT)
                self.bad_primes_info.append(
                    [p, E * E(p * T), 1 - T]
                )  #bad_primes_info.append() with 1-T as the second argument is equivalent to taking the first argument as the results (it does a convolution, as in the next line)
            else:
                self.bad_primes_info.append([p, f1, f2])

        CC = ComplexField()
        I = CC.gens()[0]
        self.sign = I**root_number_at_oo(h)
        self.sign /= I**(root_number_at_oo(h1) * V.dim)
        self.sign /= I**(root_number_at_oo(h2) * W.dim)
        self.sign *= V.sign**W.dim
        self.sign *= W.sign**V.dim
        for p in bad_primes:
            if p not in V.bad_semistable_primes or p not in V.bad_semistable_primes:
                f1 = V.local_euler_factor(p)
                f2 = W.local_euler_factor(p)
                det1 = f1.leading_coefficient() * (-1)**f1.degree()
                det2 = f2.leading_coefficient() * (-1)**f2.degree()
                n1_tame = V.dim - f1.degree()
                n2_tame = W.dim - f2.degree()
                n1_wild = ZZ(V.conductor).valuation(p) - n1_tame
                n2_wild = ZZ(W.conductor).valuation(p) - n2_tame
                # additionally, we would need to correct this by
                # replacing det1 by chi1(p) if p is semistable for V
                # however for all the possible input this currently does
                # not affect the sign
                if p in V.bad_semistable_primes:
                    chi1p = 1  # here
                else:
                    chi1p = det1
                if p in W.bad_semistable_primes:
                    chi2p = 1  # here
                else:
                    chi2p = det2

                corr = chi1p**n2_wild
                corr *= det1**n2_tame
                corr *= chi2p**n1_wild
                corr *= det2**n1_tame
                corr *= (-1)**(n1_tame * n2_tame)

                self.sign *= corr / corr.abs()

        #self.primitive = False
        self.set_dokchitser_Lfunction()
        # maybe we should change this to take as many coefficients as implemented
        # in other Lfunctions
        self.set_number_of_coefficients()

        someans = self.algebraic_coefficients(50)  # why not.
        if all(x in ZZ for x in someans):
            self.selfdual = True
        else:
            CC = ComplexField()
            self.selfdual = all(CC(an).imag().abs() < 0.0001 for an in someans)

        self.coefficient_type = max(V.coefficient_type, W.coefficient_type)
        self.coefficient_period = ZZ(V.coefficient_period).lcm(
            W.coefficient_period)
        self.ld.gp().quit()
Exemple #2
0
    def init_tensor_product(self, V, W):
        """
        We are given two Galois representations and we
        will return their tensor product.
        """
        self.original_object = V.original_object + W.original_object
        self.object_type = "tensorproduct"
        self.V1 = V
        self.V2 = W
        self.dim = V.dim * W.dim
        self.motivic_weight = V.motivic_weight + W.motivic_weight
        self.langlands = False # status 2014 :)
        self.besancon_bound = min(V.besancon_bound, W.besancon_bound)

        bad2 = ZZ(W.conductor).prime_factors()
        bad_primes = [x for x in ZZ(V.conductor).prime_factors() if x in bad2]
        for p in bad_primes:
            if ( p not in V.bad_semistable_primes and p not in W.bad_semistable_primes) :
                # this condition above only applies to the current type of objects
                # for general reps we would have to test the lines below
                # to be certain that the formulae are correct.
                #if ((p not in V.bad_semistable_primes or p not in W.bad_pot_good) and
                    #(p not in W.bad_semistable_primes or p not in V.bad_pot_good) and
                    #(p not in V.bad_semistable_primes or p not in W.bad_semistable_primes)):
                raise NotImplementedError("Currently tensor products of Galois representations are only implemented under some conditions.",
                                          "The behaviour at %d is too wild (both factors must be semistable)." % p)

        # check for the possibily of getting poles
        if V.weight == W.weight and V.conductor == W.conductor :
            Vans = V.algebraic_coefficients(50)
            Wans = W.algebraic_coefficients(50)
            CC = ComplexField()
            if ((Vans[2] in ZZ and Wans[2] in ZZ and
                all(Vans[n] == Wans[n] for n in range(1,50) ) ) or
                all( CC(Vans[n]) == CC(Wans[n]) for n in range(1,50) ) ):
                    raise NotImplementedError("It seems you are asking to tensor a "+
                                              "Galois representation with its dual " +
                                              "which results in the L-function having "+
                                              "a pole. This is not implemented here.")

        scommon = [x for x in V.bad_semistable_primes if x in W.bad_semistable_primes]

        N = W.conductor ** V.dim
        N *= V.conductor ** W.dim
        for p in bad_primes:
            n1_tame = V.dim - V.local_euler_factor(p).degree()
            n2_tame = W.dim - W.local_euler_factor(p).degree()
            nn = n1_tame * n2_tame
            N = N // p ** nn
            if p in scommon: # both are degree 1 in this case
                N = N // p
        self.conductor = N

        h1 = selberg_to_hodge(V.motivic_weight,V.mu_fe,V.nu_fe)
        h2 = selberg_to_hodge(W.motivic_weight,W.mu_fe,W.nu_fe)
        h = tensor_hodge(h1, h2)
        w,m,n = hodge_to_selberg(h)
        self.mu_fe = m
        self.nu_fe = n
        _, self.gammaV = gamma_factors(h)

        # this is used in getting the Dirichlet coefficients.
        self.bad_primes_info = []
        for p in bad_primes:
            # we have to check if this works in all bad cases !
            f1 = V.local_euler_factor(p)
            f2 = W.local_euler_factor(p)
            # might be dodgy if f1 or f2 is an approx to the Euler factor
            if p in scommon:
                E = tensor_local_factors(f1,f2,V.dim*W.dim)
                T = f1.parent().gens()[0] # right answer is E(T)*E(pT)
                self.bad_primes_info.append([p,E*E(p*T),1-T]) #bad_primes_info.append() with 1-T as the second argument is equivalent to taking the first argument as the results (it does a convolution, as in the next line)
            else:
                self.bad_primes_info.append([p,f1,f2])

        CC = ComplexField()
        I = CC.gens()[0]
        self.sign = I ** root_number_at_oo(h)
        self.sign /= I ** (root_number_at_oo(h1) * V.dim)
        self.sign /= I ** (root_number_at_oo(h2) * W.dim)
        self.sign *= V.sign ** W.dim
        self.sign *= W.sign ** V.dim
        for p in bad_primes:
            if p not in V.bad_semistable_primes or p not in V.bad_semistable_primes:
                f1 = V.local_euler_factor(p)
                f2 = W.local_euler_factor(p)
                det1 = f1.leading_coefficient() * (-1) ** f1.degree()
                det2 = f2.leading_coefficient() * (-1) ** f2.degree()
                n1_tame = V.dim - f1.degree()
                n2_tame = W.dim - f2.degree()
                n1_wild = ZZ(V.conductor).valuation(p) - n1_tame
                n2_wild = ZZ(W.conductor).valuation(p) - n2_tame
                # additionally, we would need to correct this by
                # replacing det1 by chi1(p) if p is semistable for V
                # however for all the possible input this currently does
                # not affect the sign
                if p in V.bad_semistable_primes:
                    chi1p = 1 # here
                else:
                    chi1p = det1
                if p in W.bad_semistable_primes:
                    chi2p = 1 # here
                else:
                    chi2p = det2

                corr = chi1p ** n2_wild
                corr *= det1 ** n2_tame
                corr *= chi2p ** n1_wild
                corr *= det2 ** n1_tame
                corr *= (-1) ** (n1_tame * n2_tame)

                self.sign *= corr/corr.abs()

        #self.primitive = False
        self.set_dokchitser_Lfunction()
        # maybe we should change this to take as many coefficients as implemented
        # in other Lfunctions
        self.set_number_of_coefficients()

        someans = self.algebraic_coefficients(50) # why not.
        if all( x in ZZ for x in someans):
            self.selfdual = True
        else:
            CC = ComplexField()
            self.selfdual = all( CC(an).imag().abs() < 0.0001 for an in someans)

        self.coefficient_type = max(V.coefficient_type, W.coefficient_type)
        self.coefficient_period = ZZ(V.coefficient_period).lcm(W.coefficient_period)
        self.ld.gp().quit()