def CRT_nf(reslist, Ilist, check=True): r""" Solve Chinese remainder problem over a number field. INPUT: - ``reslist`` -- a list of residues, i.e. integral number field elements - ``Ilist`` -- a list of integral ideas, assumed pairsise coprime - ``check`` (boolean, default True) -- if True, result is checked OUTPUT: An integral element x such that x-reslist[i] is in Ilist[i] for all i. """ n = len(reslist) if n == 0: # we have no parent field so this is all we can do return 0 if n == 1: return reslist[0] if n > 2: # use induction / recursion x = CRT_nf([reslist[0], CRT_nf(reslist[1:], Ilist[1:])], [Ilist[0], prod(Ilist[1:])]) if check: check_CRT_nf(reslist, Ilist, x) return x # now n=2 r = Ilist[0].element_1_mod(Ilist[1]) x = ((1 - r) * reslist[0] + r * reslist[1]).mod(prod(Ilist)) if check: check_CRT_nf(reslist, Ilist, x) return x
def factorization(original_poly): poly = ZZT(original_poly) assert poly[0] == 1 if poly == 1: return [1] try: facts = poly.factor() except NotImplementedError: try: # try to sort out the memory leak PolynomialRing( ZZ, 'T', implementation='NTL')([1] + [0] * (len(original_poly) - 2) + [1])._pari_with_name().factor() facts = PolynomialRing( ZZ, 'T', implementation='NTL')(original_poly).factor() except NotImplementedError: raise # if the factor is -1+T^2, replace it by 1-T^2 # this should happen an even number of times, mod powers out = [[-g if g[0] == -1 else g, e] for g, e in facts] assert prod( g**e for g, e in out) == poly, "%s != %s" % (prod([g**e] for g, e in out), poly) return [[g.list(), e] for g, e in out]
def upper_bound_index_cusps_in_JG_torsion(G, d, bound=60): """ INPUT: - G - a congruence subgroup - d - integer, the size of the rational cuspidal subgroup - bound (optional, default = 60) - the bound for the primes p up to which to use the hecke matrix `T_p - <p> - p` for bounding the torsion subgroup OUTPUT: - an integer `i` such that `(\#J_G(\QQ)_{tors})/d` is a divisor of `i`. EXAMPLES:: sage: from mdsage import * sage: d = rational_cuspidal_classgroup(Gamma1(23)).cardinality() sage: upper_bound_index_cusps_in_JG_torsion(Gamma1(23),d) 1 """ N = G.level() M = ModularSymbols(G) Sint = cuspidal_integral_structure(M) kill_mat = (M.star_involution().matrix().restrict(Sint) - 1) kill = kill_mat.transpose().change_ring(ZZ).row_module() for p in prime_range(3, bound): if not N % p == 0: kill += kill_torsion_coprime_to_q( p, M).restrict(Sint).change_ring(ZZ).transpose().row_module() if kill.matrix().is_square() and kill.matrix().determinant() == d: #print p break kill_mat = kill.matrix().transpose() #print N,"index of torsion in stuff killed",kill.matrix().determinant()/d if kill.matrix().determinant() == d: return 1 pm = integral_period_mapping(M) period_images1 = [ sum([M.coordinate_vector(M([c, infinity])) for c in cusps]) * pm for cusps in galois_orbits(G) ] m = (Matrix(period_images1) * kill_mat).stack(kill_mat) diag = m.change_ring(ZZ).echelon_form().diagonal() #print diag,prod(diag) assert prod(diag) == kill.matrix().determinant() / d period_images2 = [ M.coordinate_vector(M([c, infinity])) * pm for c in G.cusps() if c != Cusp(oo) ] m = (Matrix(period_images2) * kill_mat).stack(kill_mat) m, denom = m._clear_denom() diag = (m.change_ring(ZZ).echelon_form() / denom).diagonal() #print diag #print prod(i.numerator() for i in diag),"if this is 1 then :)" return prod(i.numerator() for i in diag)
def from_factors(factors, data={}): """ one may pass precomputed data via optional data parameter, e.g., euler factors """ assert len(factors) >= 2 factors.sort(key = lambda elt: (elt.degree, elt.conductor, elt.positive_zeros_arb[0])) data['motivic_weight'] = factors[0].motivic_weight assert all(data['motivic_weight'] == elt.motivic_weight for elt in factors) data['order_of_vanishing'] = sum(elt.order_of_vanishing for elt in factors) data['positive_zeros_arb'] = sorted(sum(elt.positive_zeros_arb for elt in factors, [])) data['conductor'] = prod(elt.conductor for elt in factors) if all(hasattr(elt, 'Lhash') for elt in factors): data['Lhash'] = ','.join(elt.Lhash) if all(hasattr(elt, 'label') for elt in factors): data['factors'] = [elt.label for elt in factors] if all(hasattr(elt, 'trace_hash') for elt in factors): data['trace_hash'] = sum(elt.trace_hash for elt in factors) % 0x1FFFFFFFFFFFFFFF # mod 2^61 -1 if all(hasattr(elt, 'leading_term_arb') for elt in factors): data['leading_term_arb'] = prod(elt.leading_term_arb) if all(hasattr(elt, 'root_number_acb') for elt in factors): data['root_number_acb'] = prod(elt.leading_term_arbroot_number_acb) else: # we will use this for comparisons arg = sum(elt.root_angle for elt in factors) % 1 while arg > 0.5: arg -= 1 while arg >= -0.5: arg += 1 data['root_angle'] = arg if all(hasattr(elt, 'special_values_acb') for elt in factors): data['special_values_acb'] = [prod(sv) for sv in zip(*(elt.special_values_acb for elt in factors))] if all(hasattr(elt, 'plot_delta') and hasattr(elt, 'plot_values') for elt in factors): factor_plot_values = [ [ ( j * elt.plot_delta, z) for j, z in enumerate(elt.values) ] for elt in factors] interpolations = [spline(elt) for elt in factor_plot_values] plot_range = 64.0/data['degree'] data['plot_delta'] = plot_delta = plot_range/256 # we cannot hope to get a finer resolution assert data['plot_delta'] >= max(elt.plot_delta for elt in factors) # we don't want to extrapolate data assert all(plot_range <= elt[-1][0] for elt in factor_plot_values) data['plot_values'] = [prod([elt(i) for elt in interpolations]) for i in srange(0, plot_range + plot_delta, plot_delta)] assert len(data['plot_values']) == 257 if all(hasattr(elt, 'gamma_factors') for elt in factors): data['gamma_factors'] = [sum(elt['gamma_factors'][i] for elt in factors) for i in range(2)] return lfunction_element(data)
def lambda_helper(phi, NN, p=pp): """ Helper function for affine and projective factorization probabilities. """ d = deg_fp(phi) return prod([ prod([NN(j, p) - i for i in range(m1(phi, j))]) // prod([factorial(m2(phi, [j, i])) for i in range(1, d + 1)]) for j in range(1, d + 1) ])
def dbd(self, d): """ Return matrix of <d>. INPUT: - `d` -- integer OUTPUT: - a matrix modulo 2 EXAMPLES:: sage: from mdsage import * sage: C = KamiennyCriterion(29) sage: C.dbd(2) 22 x 22 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries) sage: C.dbd(2)^14==1 True sage: C.dbd(2)[0] (0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1) """ d=ZZ(d) if self.verbose: tm = cputime(); mem = get_memory_usage(); print "dbd start" try: return self._dbd[d % self.p] except AttributeError: pass # Find generators of the integers modulo p: gens = Integers(self.p).unit_gens() orders = [g.multiplicative_order() for g in gens] # Compute corresponding <z> operator on integral cuspidal modular symbols X = [self.M.diamond_bracket_operator(z).matrix() for z in gens] if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "create d" X = [x.restrict(self.S_integral, check=False) for x in X] if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "restrict d" X = [matrix_modp(x) for x in X] if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "mod d" # Take combinations to make list self._dbd of all dbd's such that # self._dbd[d] = <d> from itertools import product v = [None] * self.p for ei in product(*[range(i) for i in orders]): di = prod(g**e for e,g in zip(ei,gens)).lift() m = prod(g**e for e,g in zip(ei,X)) v[di] = m if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "mul" assert v.count(None) == (self.p-euler_phi(self.p)) self._dbd = v if self.verbose: print "time and mem", cputime(tm), get_memory_usage(mem), "bdb finnished" return v[d % self.p]
def dbd(self, d): """ Return matrix of <d>. INPUT: - `d` -- integer OUTPUT: - a matrix modulo 2 EXAMPLES:: sage: from mdsage import * sage: C = KamiennyCriterion(29) sage: C.dbd(2) 22 x 22 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries) sage: C.dbd(2)^14==1 True sage: C.dbd(2)[0] (0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1) """ d=ZZ(d) if self.verbose: tm = cputime(); mem = get_memory_usage(); print("dbd start") try: return self._dbd[d % self.p] except AttributeError: pass # Find generators of the integers modulo p: gens = Integers(self.p).unit_gens() orders = [g.multiplicative_order() for g in gens] # Compute corresponding <z> operator on integral cuspidal modular symbols X = [self.M.diamond_bracket_operator(z).matrix() for z in gens] if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "create d") X = [x.restrict(self.S_integral, check=False) for x in X] if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "restrict d") X = [matrix_modp(x) for x in X] if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "mod d") # Take combinations to make list self._dbd of all dbd's such that # self._dbd[d] = <d> from itertools import product v = [None] * self.p for ei in product(*[list(range(i)) for i in orders]): di = prod(g**e for e,g in zip(ei,gens)).lift() m = prod(g**e for e,g in zip(ei,X)) v[di] = m if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "mul") assert v.count(None) == (self.p-euler_phi(self.p)) self._dbd = v if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "bdb finnished") return v[d % self.p]
def upper_bound_index_cusps_in_JG_torsion(G,d, bound = 60): """ INPUT: - G - a congruence subgroup - d - integer, the size of the rational cuspidal subgroup - bound (optional, default = 60) - the bound for the primes p up to which to use the hecke matrix `T_p - <p> - p` for bounding the torsion subgroup OUTPUT: - an integer `i` such that `(\#J_G(\QQ)_{tors})/d` is a divisor of `i`. EXAMPLES:: sage: from mdsage import * sage: d = rational_cuspidal_classgroup(Gamma1(23)).cardinality() sage: upper_bound_index_cusps_in_JG_torsion(Gamma1(23),d) 1 """ N = G.level() M=ModularSymbols(G); Sint=cuspidal_integral_structure(M) kill_mat=(M.star_involution().matrix().restrict(Sint)-1) kill=kill_mat.transpose().change_ring(ZZ).row_module() for p in prime_range(3,bound): if not N % p ==0: kill+=kill_torsion_coprime_to_q(p,M).restrict(Sint).change_ring(ZZ).transpose().row_module() if kill.matrix().is_square() and kill.matrix().determinant()==d: #print p break kill_mat=kill.matrix().transpose() #print N,"index of torsion in stuff killed",kill.matrix().determinant()/d if kill.matrix().determinant()==d: return 1 pm=integral_period_mapping(M) period_images1=[sum([M.coordinate_vector(M([c,infinity])) for c in cusps])*pm for cusps in galois_orbits(G)] m=(Matrix(period_images1)*kill_mat).stack(kill_mat) diag=m.change_ring(ZZ).echelon_form().diagonal() #print diag,prod(diag) assert prod(diag)==kill.matrix().determinant()/d period_images2=[M.coordinate_vector(M([c,infinity]))*pm for c in G.cusps() if c != Cusp(oo)] m=(Matrix(period_images2)*kill_mat).stack(kill_mat) m,denom=m._clear_denom() diag=(m.change_ring(ZZ).echelon_form()/denom).diagonal() #print diag #print prod(i.numerator() for i in diag),"if this is 1 then :)" return prod(i.numerator() for i in diag)
def monom(par): ''' Given a partition ``par`` = :math:`\\left[0^{i_0},1^{i_1},\\ldots,n^{i_n}\\right]` return a monomial (in Multivariate Polynomial Ring over Q) :math:`{t_0}^{i_0}\\cdot\\ldots\\cdot{t_n}^{i_n} \\big/ {i_0}!\\cdot\\ldots\\cdot{i_n}!`. EXAMPLE: Here we generate all monomials of weight 5:: sage: from cvolume.series import monom sage: [monom(l) for l in Partitions(5)] [t4, t0*t3, t1*t2, 1/2*t0^2*t2, 1/2*t0*t1^2, 1/6*t0^3*t1, 1/120*t0^5] ''' exp = par.to_exp() return prod(ZZ(1)/factorial(k) for k in exp)*prod([T_vars[i-1] for i in par])
def mittag_leffler_e(alpha, beta=1): alpha = QQ.coerce(alpha) if alpha <= QQ.zero(): raise ValueError num, den = alpha.numerator(), alpha.denominator() dop0 = prod(alpha * x * Dx + beta - num + t for t in range(num)) - x**den expo = dop0.indicial_polynomial(x).roots(QQ, multiplicities=False) pre = prod((x * Dx - k) for k in range(den) if QQ(k) not in expo) dop = pre * dop0 # homogenize dop = dop.numerator().primitive_part() expo = sorted(dop.indicial_polynomial(x).roots(QQ, multiplicities=False)) assert len(expo) == dop.order() ini = [(1 / funs.gamma(alpha * k + beta) if k in ZZ else 0) for k in expo] return IVP(0, dop, ini)
def __get_lcm(self, input): r''' Auxiliary method for computing the lcm of a sequence. Private method for computing a common multiple of a sequence given in ``input``. This method relies on the Sage implementation of ``lcm`` and, if this fails tries to compute a least common multiple using the GCD of the sequence: .. MATH:: lcm(a_1,\ldots,a_n) = \frac{a_1 \cdots a_n}{gcd(a_1,\ldots,a_n)}. In case the computation of the gcd fails again, we just return the product of all the elements of the input. ''' try: return lcm(input) except AttributeError: ## No lcm for this class, implementing a general lcm try: ## Relying on gcd p = self.__parent res = p(1) for el in input: res = p((res * el) / gcd(res, el)) return res except AttributeError: ## Returning the product of everything return prod(input)
def _prod_f_A_G(Gs, kappa, psi, psi2): """ Used in the computation of product. Do not call directly. """ result = 1 G = Gs.G.strataG for v in range(1, G.num_vertices() + 1): result *= prod( (sum((kappa.get((j, w), 0) for w in Gs.alpha_inv[v]))**f for j, f in G.kappa_on_v(v))) * prod( (Gs.psi_no_loop(edge, v, ex, psi) for edge, ex in G.psi_no_loop_on_v(v))) * prod( (Gs.psi_loop(edge, v, ex1, ex2, psi, psi2) for edge, ex1, ex2 in G.psi_loop_on_v(v))) return result
def __init__(self, tiling_engine, bits_prec=53): self.RIF = RealIntervalField(bits_prec) self.CIF = ComplexIntervalField(bits_prec) self.baseTetInCenter = FinitePoint( self.CIF(tiling_engine.baseTetInCenter.z), self.RIF(tiling_engine.baseTetInCenter.t)) self.generator_matrices = { g: m.change_ring(self.CIF) for g, m in tiling_engine.mcomplex.GeneratorMatrices.items() } self.max_values = {} for tile in tiling_engine.all_tiles(): if tile.word: matrix = prod(self.generator_matrices[g] for g in tile.word) tileCenter = FinitePoint(self.CIF(tile.center.z), self.RIF(tile.center.t)) err = tileCenter.dist( self.baseTetInCenter.translate_PSL(matrix)).upper() l = len(tile.word) self.max_values[l] = max(err, self.max_values.get(l, err))
def __init__(self, tiling_engine, bits_prec=2 * 53): self.RIF = RealIntervalField(bits_prec) self.CIF = ComplexIntervalField(bits_prec) self.baseTetInCenter = vector( self.RIF, complex_and_height_to_R13_time_vector( tiling_engine.baseTetInCenter.z, tiling_engine.baseTetInCenter.t)) self.generator_matrices = { g: matrix(self.RIF, PSL2C_to_O13(m)) for g, m in tiling_engine.mcomplex.GeneratorMatrices.items() } self.max_values = {} for tile in tiling_engine.all_tiles(): if tile.word: m = prod(self.generator_matrices[g] for g in tile.word) tileCenter = vector( self.RIF, complex_and_height_to_R13_time_vector( tile.center.z, tile.center.t)) #print("=====") #print(tileCenter) #print(m * self.baseTetInCenter) #print(inner_prod(m * self.baseTetInCenter, tileCenter).endpoints()) err = my_dist(m * self.baseTetInCenter, tileCenter).upper() l = len(tile.word) self.max_values[l] = max(err, self.max_values.get(l, err))
def fractional_CRT_split(residues, ps_roots, K, BI_coordinates = None): if K is QQ: return fractional_CRT_QQ(residues, ps_roots); OK = K.ring_of_integers(); BOK = OK.basis(); residues_ZZ = [ r.lift() for r in residues]; primes = [p for p, _ in ps_roots]; lift = CRT_list(residues_ZZ, primes); lift_coordinates = OK.coordinates(lift); if BI_coordinates is None: p_ideals = [ OK.ideal(p, K.gen() - root) for p, root in ps_roots ]; I = prod(p_ideals); BI = I.basis(); # basis as a ZZ-module BI_coordinates = [ OK.coordinates(b) for b in BI ]; M = Matrix(Integers(), [ [ kronecker_delta(i,j) for j,_ in enumerate(BOK) ] + [ lift_coordinates[i] ] + [ b[i] for b in BI_coordinates ] for i in range(len(BOK)) ]) # v = short_vector Kernel_Basis = Matrix(Integers(), M.transpose().kernel().basis()) v =Kernel_Basis.LLL()[0]; #print v[:len(BOK)] if v[len(BOK)] == 0: return 0; return (-1/v[len(BOK)]) * sum( v[i] * b for i, b in enumerate(BOK));
def _sqrt(f): if not f: return f li = list(f.factor()) if any(e % 2 for _, e in li): raise ValueError('not a square') return f.parent(prod(a**(e//2) for (a,e) in li))
def _perform_word_moves(matrices, G): mats = [None] + matrices moves = G._word_moves() while moves: a = moves.pop(0) if a >= len(mats): # new generator added n = moves.index(a) # end symbol location word, moves = moves[:n], moves[n + 1:] mats.append( prod([mats[g] if g > 0 else _adjoint2(mats[-g]) for g in word])) else: b = moves.pop(0) if a == b: # generator removed mats[a] = mats[-1] mats = mats[:-1] elif a == -b: # invert generator mats[a] = _adjoint2(mats[a]) else: #handle slide A, B = mats[abs(a)], mats[abs(b)] if a * b < 0: B = _adjoint2(B) mats[abs(a)] = A * B if a > 0 else B * A return mats[1:G.num_generators() + 1]
def HermiteInterpolation(points_list): """ return a polynomial that pass trough the given points with the given derivatives. Each element of points_list is a triple (x,y,d) and the given polynomial satisfies P(x)=y and P'(x)=d EXAMPLES : sage : P=HermiteInterpolation( [ (1,14,7),(3,64,51),(-2,-16,31) ] ) sage: P.simplify_full() 2*x^3 - x^2 + 3*x + 10 """ x = var('x') n = len(points_list) xx = {i: points_list[i][0] for i in range(0, n)} y = {i: points_list[i][1] for i in range(0, n)} d = {i: points_list[i][2] for i in range(0, n)} b = {i: (x - xx[i])**2 for i in range(0, n)} Q = {} for j in range(0, n): Q[j] = prod([b[i] for i in range(0, n) if i <> j]) P = {} for j in range(0, n): parenthese = 1 - (x - xx[j]) * Q[j].diff(x)(xx[j]) / Q[j](xx[j]) P[j] = (Q[j](x) / Q[j](xx[j])) * (parenthese * y[j] + (x - xx[j]) * d[j]) f = sum(P.values()) return phyFunction(f.expand())
def pgl2_matrix_for_path(self, p): if p: return prod([self.pgl2_matrix_for_edge(e) for e in p[::-1]]) else: RF = self.vertex_gram_matrices[0].base_ring() CF = RF.complex_field() return matrix.identity(CF, 2)
def global_minimality_class(E): r""" Returns the ideal class representing the obstruction to this elliptic curve having a global minimal model. INPUT: - ``E`` -- an elliptic curve over a number field OUTPUT: An ideal class of the base number field, which is trivial if and only if E has a global minimal model, and which can be used to find global and semi-global minimal models. """ K = E.base_field() Cl = K.class_group() if K.class_number() == 1: return Cl(1) D = E.discriminant() dat = E.local_data() primes = [d.prime() for d in dat] vals = [d.discriminant_valuation() for d in dat] I = prod([P ** ((D.valuation(P) - v) // 12) for P, v in zip(primes, vals)], E.base_field().ideal(1)) return Cl(I)
def NonCubicSet(K,S, verbose=False): u = -1 if K==QQ else K(K.unit_group().torsion_generator()) from KSp import IdealGenerator Sx = [u] + [IdealGenerator(P) for P in S] r = len(Sx) d123 = r + binomial(r,2) + binomial(r,3) vecP = vec123(K,Sx) A = Matrix(GF(2),0,d123) N = prod(S,1) primes = primes_iter(K,None) T = [] while A.rank() < d123: p = primes.next() while p.divides(N): p = primes.next() v = vecP(p) if verbose: print("v={}".format(v)) A1 = A.stack(vector(v)) if A1.rank() > A.rank(): A = A1 T.append(p) if verbose: print("new A={} with {} rows and {} cols".format(A,A.nrows(),A.ncols())) print("T increases to {}".format(T)) return T
def get_T2(K, S, unit_first=True, verbose=False): u = -1 if K==QQ else K(K.unit_group().torsion_generator()) from KSp import IdealGenerator Sx = [IdealGenerator(P) for P in S] if unit_first: Sx = [u] + Sx else: Sx = Sx + [u] r = len(Sx) r2 = r*(r-1)//2 N = prod(S,1) T2 = {} primes = primes_iter(K,1) p = primes.next() while len(T2)<r+r2: p = primes.next() while p.divides(N): p = primes.next() # Compute the values alpha_p(Delta) for Delta in Sx: ro = alphalist(p,Sx) # Compute the set I(P) of i for which alpha_p(Delta_i)=1: ij = Set([i for i,vi in enumerate(ro) if vi]) if verbose: print("P={}, I(P)={}".format(p,ij)) # Keep I(p) and p if #I(p)=1 or 2 and it's a new subset@ if len(ij) in [1,2] and not ij in T2: T2[ij] = p return T2
def __init__(self, K, F, minimal_ramification=1): minimal_ramification = ZZ(minimal_ramification) # print "entering WeakPadicGaloisExtension with" # print "F = %s"%F # if F is a polynomial, replace it by the list of its irreducible factors # if isinstance(F, Polynomial): # F = [f for f, m in F.factor()] assert K.is_Qp(), "for the moment, K has to be Q_p" # assert not K.p().divides(minimal_ramification), "minimal_ramification has to be prime to p" if not isinstance(F, Polynomial): if F == []: F = PolynomialRing(K.number_field(), 'x')(1) else: F = prod(F) self._base_field = K L = K.weak_splitting_field(F) e = ZZ(L.absolute_ramification_degree() / K.absolute_ramification_degree()) if not minimal_ramification.divides(e): # enlarge the absolute ramification index of vL # such that minimal_ramification divides e(vL/vK): m = ZZ(minimal_ramification / e.gcd(minimal_ramification)) # assert not self.p().divides(m), "p = %s, m = %s, e = %s,\nminimal_ramification = %s"%(self.p(), m, e, minimal_ramification) L = L.ramified_extension(m) # if m was not prime to p, L/K may not be weak Galois anymore else: m = ZZ(1) self._extension_field = L self._ramification_degree = e * m self._degree = ZZ(L.absolute_degree() / K.absolute_degree()) self._inertia_degree = ZZ(L.absolute_inertia_degree() / K.absolute_inertia_degree()) assert self._degree == self._ramification_degree * self._inertia_degree
def cardinality(self): r""" Return the cardinality of self EXAMPLES:: sage: S = Subsets([1,1,2,3],submultiset=True) sage: S.cardinality() 12 sage: len(S.list()) 12 sage: S = Subsets([1,1,2,2,3],submultiset=True) sage: S.cardinality() 18 sage: len(S.list()) 18 sage: S = Subsets([1,1,1,2,2,3],submultiset=True) sage: S.cardinality() 24 sage: len(S.list()) 24 """ from sage.all import prod return Integer(prod(k + 1 for k in self._d.values()))
def taylor_processor_factored(new_ring, Phi, scalar, alpha, I, omega): k = alpha.nrows() - 1 tau = SR.var('tau') y = [SR('y%d' % i) for i in range(k + 1)] R = PolynomialRing(QQ, len(y), y) beta = [a * Phi for a in alpha] ell = len(I) def f(i): if i == 0: return QQ(scalar) * y[0] * exp(tau * omega[0]) elif i in I: return tau / (1 - exp(tau * omega[i])) else: return 1 / (1 - y[i] * exp(tau * omega[i])) H = [ f(i).series(tau, ell + 1).truncate().collect(tau) for i in range(k + 1) ] for i in range(k + 1): H[i] = [H[i].coefficient(tau, j) for j in range(ell + 1)] r = [] # Get coefficient of tau^ell in prod(H) for w in NonnegativeCompositions(ell, k + 1): r = prod( CyclotomicRationalFunction.from_split_expression(H[i][ w[i]], y, R).monomial_substitution(new_ring, beta) for i in range(k + 1)) yield r
def cardinality(self): r""" Return the cardinality of self EXAMPLES:: sage: S = Subsets([1,1,2,3],submultiset=True) sage: S.cardinality() 12 sage: len(S.list()) 12 sage: S = Subsets([1,1,2,2,3],submultiset=True) sage: S.cardinality() 18 sage: len(S.list()) 18 sage: S = Subsets([1,1,1,2,2,3],submultiset=True) sage: S.cardinality() 24 sage: len(S.list()) 24 """ from sage.all import prod return Integer(prod(k+1 for k in self._d.values()))
def global_minimality_class(E): r""" Returns the ideal class representing the obstruction to this elliptic curve having a global minimal model. INPUT: - ``E`` -- an elliptic curve over a number field OUTPUT: An ideal class of the base number field, which is trivial if and only if E has a global minimal model, and which can be used to find global and semi-global minimal models. """ K = E.base_field() Cl = K.class_group() if K.class_number() == 1: return Cl(1) D = E.discriminant() dat = E.local_data() primes = [d.prime() for d in dat] vals = [d.discriminant_valuation() for d in dat] I = prod([P**((D.valuation(P) - v) // 12) for P, v in zip(primes, vals)], E.base_field().ideal(1)) return Cl(I)
def operator(Poly): ''' Return the result of application of :math:`\\mathcal{Z}`-operator to the polynomial. ''' return sum( Poly.monomial_coefficient(monom) * prod(replmon(k) for k in monom.exponents()[0]) for monom in Poly.monomials())
def convert_laurent_to_poly(elt, expshift, P): if elt == 0: return P(0) return sum([ c * prod([g**e for g, e in zip(P.gens(), vector(exps) + expshift)]) for c, exps in zip(elt.coefficients(), uniform_poly_exponents(elt)) ])
def fractional_CRT_QQ(residues, ps_roots): residues_ZZ = [ r.lift() for r in residues]; primes = [p for p, _ in ps_roots] lift = CRT_list(residues_ZZ, primes); N = prod(primes); M = Matrix([[1 ,lift, N]]); short_vector = Matrix(M.transpose().kernel().basis()).LLL()[0] return -short_vector[0]/short_vector[1];
def an_dict_from_ap(ap, N, B): r""" Give a dict ``ap`` of the `a_p`, for primes with norm up to `B`, return the dictionary giving all `a_I` for all ideals `I` up to norm `B`. NOTE: This code is specific to Dirichlet series of elliptic curves. INPUT: - ``ap`` -- dictionary of ap, as output, e.g., by the ap_dict function - `N` -- ideal; conductor of the elliptic curve - `B` -- positive integer OUTPUT: dictionary mapping reduced rep of primes (N(p),p.reduced_gens()) of ideals to integers NOTE: This should be really, really slow. It's really just a toy reference implementation. """ from sage.all import prod # used below F = N.number_field() A = F.ideals_of_bdd_norm(B) an = dict(ap) for n in sorted(A.keys()): X = A[n] for I in X: if reduced_rep(I) in an: # prime case, already done pass else: # composite case fac = I.factor() if len(fac) == 0: # unit ideal an[reduced_rep(I)] = ZZ(1) elif len(fac) > 1: # not a prime power, so just multiply together # already known Dirichlet coefficients, for # prime power divisors (which are all known). an[reduced_rep(I)] = prod(an[reduced_rep(p**e)] for p, e in fac) else: p, e = fac[0] # a prime power if p.divides(N): # prime divides level an[reduced_rep(I)] = an[reduced_rep(p)]**e else: # prime doesn't divide conductor: a_{p^e} = a_p*a_{p^(e-1)} - Norm(p)*a_{p^(e-2)} assert e >= 2 an[reduced_rep(I)] = ( an[reduced_rep(p)] * an[reduced_rep(p**(e - 1))] - p.norm() * an[reduced_rep(p**(e - 2))]) return an
def allgens(line): r""" Parses one line from an allgens file. Returns the label and a dict containing fields with keys 'conductor', 'iso', 'number', 'ainvs', 'jinv', 'cm', 'rank', 'gens', 'torsion_order', 'torsion_structure', 'torsion_generators', all values being strings or ints. Input line fields: conductor iso number ainvs rank torsion_structure gens torsion_gens Sample input line: 20202 i 2 [1,0,0,-298389,54947169] 1 [2,4] [-570:6603:1] [-622:311:1] [834:19239:1] """ data = split(line) label = data[0] + data[1] + data[2] rank = int(data[4]) t = data[5] if t == '[]': t = [] else: t = [int(c) for c in t[1:-1].split(",")] torsion = int(prod([ti for ti in t], 1)) ainvs = parse_ainvs(data[3]) E = EllipticCurve([ZZ(a) for a in ainvs]) jinv = unicode(str(E.j_invariant())) if E.has_cm(): cm = int(E.cm_discriminant()) else: cm = int(0) content = { 'conductor': int(data[0]), 'iso': data[0] + data[1], 'number': int(data[2]), 'ainvs': ainvs, 'jinv': jinv, 'cm': cm, 'rank': int(data[4]), 'gens': ["(%s)" % gen[1:-1] for gen in data[6:6 + rank]], 'torsion': torsion, 'torsion_structure': ["%s" % tor for tor in t], 'torsion_generators': ["%s" % parse_tgens(tgens[1:-1]) for tgens in data[6 + rank:]], } extra_data = make_extra_data(label, content['number'], ainvs, content['gens']) content.update(extra_data) return label, content
def get_T0_mod3(K,S, flist=None, verbose=False): # Compute all absolutely irreducible quartics unramified outside S # if not supplied: if flist == None: from S4 import abs_irred_extensions flist = abs_irred_extensions(K,S) if verbose: print("quartics: {}".format(flist)) # Append a poly with lam3=0 x = polygen(K) flist0 = flist + [x**3] n = len(flist) # Starting with no primes, compute the lambda matrix plist = [] vlist = [lamvec(f,plist,lam3) for f in flist0] ij = equal_vecs(vlist) if verbose: print("With plist={}, vlist={}, ij={}".format(plist,vlist,ij)); N = prod(S,1) * prod([f.discriminant() for f in flist]) # As long as the vectors in vlist are not all distinct, find two # indices i,j for which they are the same and find a new prime which # distinguishes these two, add it to the list and update. The primes # must not be in S or divide the discriminant of any of the quartics. while ij: i,j = ij if j==n: p = get_p_1(K,flist[i],N, lam3) else: p = get_p_2(K,flist[i],flist[j],N, lam3) plist = plist + [p] if verbose: print("plist = {}".format(plist)) vlist = [lamvec(f,plist,lam3) for f in flist0] ij = equal_vecs(vlist) if verbose: print("With plist={}, vlist={}, ij={}".format(plist,vlist,ij)); vlist = vlist[:-1] # Sort the primes into order and recompute the vectors: plist.sort() vlist = [lamvec(f,plist,lam3) for f in flist] return flist, plist, vlist
def an_dict_from_ap(ap, N, B): r""" Give a dict ``ap`` of the `a_p`, for primes with norm up to `B`, return the dictionary giving all `a_I` for all ideals `I` up to norm `B`. NOTE: This code is specific to Dirichlet series of elliptic curves. INPUT: - ``ap`` -- dictionary of ap, as output, e.g., by the ap_dict function - `N` -- ideal; conductor of the elliptic curve - `B` -- positive integer OUTPUT: dictionary mapping reduced rep of primes (N(p),p.reduced_gens()) of ideals to integers NOTE: This should be really, really slow. It's really just a toy reference implementation. """ from sage.all import prod # used below F = N.number_field() A = F.ideals_of_bdd_norm(B) an = dict(ap) for n in sorted(A.keys()): X = A[n] for I in X: if an.has_key(reduced_rep(I)): # prime case, already done pass else: # composite case fac = I.factor() if len(fac) == 0: # unit ideal an[reduced_rep(I)] = ZZ(1) elif len(fac) > 1: # not a prime power, so just multiply together # already known Dirichlet coefficients, for # prime power divisors (which are all known). an[reduced_rep(I)] = prod(an[reduced_rep(p**e)] for p, e in fac) else: p, e = fac[0] # a prime power if p.divides(N): # prime divides level an[reduced_rep(I)] = an[reduced_rep(p)]**e else: # prime doesn't divide conductor: a_{p^e} = a_p*a_{p^(e-1)} - Norm(p)*a_{p^(e-2)} assert e >= 2 an[reduced_rep(I)] = (an[reduced_rep(p)] * an[reduced_rep(p**(e-1))] - p.norm()*an[reduced_rep(p**(e-2))]) return an
def ppower_norm_ideal_from_label(K, lab): r""" return the ideal of prime-power norm from its label. """ n, i = [int(c) for c in lab.split(".")] p, f = ZZ(n).factor()[0] make_keys(K, p) PP = K.primes_dict[p] ff = [P.residue_class_degree() for P in PP] vec = exp_vec_wt(f, ff)[i - 1] return prod([P**v for P, v in zip(PP, vec)])
def euler_p_factor(root_list, PREC): ''' computes the coefficients of the pth Euler factor expanded as a geometric series ax^n is the Dirichlet series coefficient p^(-ns) ''' PREC = floor(PREC) # return satake_list R = LaurentSeriesRing(CF, 'x') x = R.gens()[0] ep = prod([1 / (1 - a * x) for a in root_list]) return ep + O(x ** (PREC + 1))
def factorization(original_poly): poly = ZZT(original_poly) assert poly[0] == 1 if poly == 1: return [1] try: facts = poly.factor() except NotImplementedError: try: # try to sort out the memory leak PolynomialRing(ZZ, 'T', implementation='NTL')([1] + [0]*(len(original_poly) - 2) + [1])._pari_with_name().factor() facts = PolynomialRing(ZZ, 'T', implementation='NTL')(original_poly).factor() except NotImplementedError: raise # if the factor is -1+T^2, replace it by 1-T^2 # this should happen an even number of times, mod powers out = [[-g if g[0] == -1 else g, e] for g, e in facts] assert prod( g**e for g, e in out ) == poly, "%s != %s" % (prod( [g**e] for g, e in out ), poly) return [[g.list(), e] for g,e in out]
def level_attributes(level): # returns level_radical, level_primes, level_is_prime, level_is_prime_power, level_is_squarefree, level_is_square fact = Integer(level).factor() level_primes = [elt[0] for elt in fact] level_radical = prod(level_primes) level_is_prime_power = len(fact) == 1 level_is_prime = level_is_prime_power and level_radical == level level_is_square = all( elt[1] % 2 == 0 for elt in fact) level_is_squarefree = all( elt[1] == 1 for elt in fact) return [level_radical, level_primes, level_is_prime, level_is_prime_power, level_is_squarefree, level_is_square]
def ppower_norm_ideal_from_label(K,lab): r""" return the ideal of prime-power norm from its label. """ n, i = [int(c) for c in lab.split(".")] p, f = ZZ(n).factor()[0] make_keys(K,p) PP = K.primes_dict[p] ff = [P.residue_class_degree() for P in PP] vec = exp_vec_wt(f,ff)[i-1] return prod([P**v for P,v in zip(PP,vec)])
def make_mwbsd(self): mwbsd = self.mwbsd = db.ec_mwbsd.lookup(self.lmfdb_label) # Some components are in the main table: mwbsd['rank'] = r = self.rank mwbsd['torsion'] = self.torsion mwbsd['reg'] = self.regulator mwbsd['sha'] = self.sha mwbsd['sha2'] = latex_sha(self.sha) # Integral points xintcoords = mwbsd['xcoord_integral_points'] a1, _, a3, _, _ = ainvs = self.ainvs if a1 or a3: int_pts = sum([[(x, y) for y in make_y_coords(ainvs, x)] for x in xintcoords], []) mwbsd['int_points'] = ', '.join(web_latex(P) for P in int_pts) else: int_pts = [(x, make_y_coords(ainvs, x)[0]) for x in xintcoords] mwbsd['int_points'] = ', '.join(pm_pt(P) for P in int_pts) # Generators (mod torsion) and heights: mwbsd['generators'] = [ web_latex(weighted_proj_to_affine_point(P)) for P in mwbsd['gens'] ] if mwbsd['ngens'] else '' # Torsion structure and generators: if mwbsd['torsion'] == 1: mwbsd['tor_struct'] = '' mwbsd['tor_gens'] = '' else: mwbsd['tor_struct'] = r' \times '.join( [r'\Z/{%s}\Z' % n for n in self.torsion_structure]) mwbsd['tor_gens'] = ', '.join( web_latex(weighted_proj_to_affine_point(P)) for P in mwbsd['torsion_generators']) # BSD invariants if r >= 2: mwbsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r, r) elif r: mwbsd['lder_name'] = "L'(E,1)" else: mwbsd['lder_name'] = "L(E,1)" tamagawa_numbers = [ld['tamagawa_number'] for ld in self.local_data] cp_fac = [ZZ(cp).factor() for cp in tamagawa_numbers] cp_fac = [ latex(cp) if len(cp) < 2 else '(' + latex(cp) + ')' for cp in cp_fac ] mwbsd['tamagawa_factors'] = r'\cdot'.join(cp_fac) mwbsd['tamagawa_product'] = prod(tamagawa_numbers)
def get_coeffs_p_over_nf(curve, prime_number, accuracy=20 , conductor=None): """ Computes the inverse of product of L_prime on all primes above prime_number, then returns power series of L_p up to desired accuracy. But will not return power series if need not do so (depends on accuracy). """ if conductor is None: conductor = curve.conductor() primes = curve.base_field().prime_factors(prime_number) series_p = [get_factor_over_nf(curve, prime_id, prime_number, conductor, accuracy) for prime_id in primes] return ( prod(series_p).O(accuracy) )**(-1)
def ideals_of_norm(K,n): r""" Return a list of all ideals of norm n (sorted). Cached. """ if not hasattr(K,'ideal_norm_dict'): K.ideal_norm_dict = {} if not n in K.ideal_norm_dict: if n==1: K.ideal_norm_dict[n] = [K.ideal(1)] else: K.ideal_norm_dict[n] = [prod(Q) for Q in cartesian_product_iterator([ppower_norm_ideals(K,p,e) for p,e in n.factor()])] return K.ideal_norm_dict[n]
def X_to_kappa(f,kappa): """ f -- A polynomial in X. The constant term is ignored. kappa -- A function so that kappa(a) is kappa_a. Returns:: A polynomial in kappas, converting ... """ psi_list = [] for expon,coef in f.dict().items(): #print expon[0], coef if expon[0] !=0: psi_list += [expon[0]]*coef #print psi_list result = 0 for p in SetPartitions(range(len(psi_list))): #print p #print [ kappa( sum((psi_list[i] for i in s)) ) for s in p] result += prod((factorial(len(s) - 1) for s in p)) * prod(( kappa( sum((psi_list[i] for i in s)) ) for s in p )) return result
def alpha_alt(roots, p): """ Computes invariant alpha in the 'ALT' case """ from sage.all import prod, Permutation tmp = prod(roots[i] - roots[j] for i in range(len(roots)) for j in range(i)) try: frob_perm = Permutation(alternating_group(frobenius_permutation(roots, p))) except TypeError: raise TypeError("The Frobenius element does not generate an element of the alternating group") sign = -(-1) ** are_conjugate_in_alternating(frob_perm, data_perm) return tmp * sign
def test_spanning_trees(self): r""" Test coset representatives obtained from spanning trees for even subgroup (Kulkarni's method with generators ``S2``, ``S3`` and Verrill's method with generators ``L``, ``S2``). EXAMPLES:: sage: from sage.modular.arithgroup.tests import Test sage: Test().test_spanning_trees() #random """ from sage.all import prod from all import SL2Z from arithgroup_perm import S2m,S3m,Lm G = random_even_arithgroup(self.index) m = {'l':Lm, 's':S2m} tree,reps,wreps,gens = G._spanning_tree_verrill() assert reps[0] == SL2Z([1,0,0,1]) assert wreps[0] == '' for i in xrange(1,self.index): assert prod(m[letter] for letter in wreps[i]) == reps[i] tree,reps,wreps,gens = G._spanning_tree_verrill(on_right=False) assert reps[0] == SL2Z([1,0,0,1]) assert wreps[0] == '' for i in xrange(1,self.index): assert prod(m[letter] for letter in wreps[i]) == reps[i] m = {'s2':S2m, 's3':S3m} tree,reps,wreps,gens = G._spanning_tree_kulkarni() assert reps[0] == SL2Z([1,0,0,1]) assert wreps[0] == [] for i in xrange(1,self.index): assert prod(m[letter] for letter in wreps[i]) == reps[i] tree,reps,wreps,gens = G._spanning_tree_kulkarni(on_right=False) assert reps[0] == SL2Z([1,0,0,1]) assert wreps[0] == [] for i in xrange(1,self.index): assert prod(m[letter] for letter in wreps[i]) == reps[i]
def _prod_f_A_G(Gs, kappa, psi, psi2): """ Used in the computation of product. Do not call directly. """ result = 1 G = Gs.G.strataG A = Gs.A.strataG for v in range(1,G.num_vertices()+1): #print "Gs", Gs #print "G,g",v result *= prod(( sum((kappa.get((j,w),0) for w in Gs.alpha_inv[v]))**f for j,f in G.kappa_on_v(v))) * prod(( Gs.psi_no_loop(edge,v,ex,psi) for edge, ex in G.psi_no_loop_on_v(v) )) * prod(( Gs.psi_loop(edge,v, ex1, ex2, psi,psi2) for edge, ex1, ex2 in G.psi_loop_on_v(v) )) return result
def ppower_norm_ideals(K,p,f): r""" Return a sorted list of ideals of K of norm p^f with p prime """ make_keys(K,p) if not hasattr(K,'ppower_dict'): K.ppower_dict = {} if not (p,f) in K.ppower_dict: PP = K.primes_dict[p] # These vectors are sorted, first by unweighted weight (sum of # values) then lexicographically with the reverse ordering on Z: vv = exp_vec_wt(f,[P.residue_class_degree() for P in PP]) Qs = [prod([P**v for P,v in zip(PP,v)]) for v in vv] K.ppower_dict[(p,f)] = Qs return K.ppower_dict[(p,f)]
def galrep(line, new_format=True): r""" Parses one line from a galrep file. Returns the label and a dict containing two fields: 'nonmax_primes', a list of primes p for which the Galois representation modulo p is not maximal, 'modp_images', a list of strings encoding the image when not maximal, following Sutherland's coding scheme for subgroups of GL(2,p). Note that these codes start with a 1 or 2 digit prime followed a letter in ['B','C','N','S']. Input line fields (new_format=False): conductor iso number ainvs rank torsion codes Sample input line: 66 c 3 [1,0,0,-10065,-389499] 0 2 2B 5B.1.2 Input line fields (new_format=True): label codes Sample input line: 66c3 2B 5B.1.2 """ data = split(line) if new_format: label = data[0] image_codes = data[1:] else: label = data[0] + data[1] + data[2] image_codes = data[6:] pr = [ int(split_galois_image_code(s)[0]) for s in image_codes] if new_format: d = { 'nonmax_primes': pr, 'nonmax_rad': prod(pr), 'modp_images': image_codes, } else: d = { 'non-surjective_primes': pr, 'galois_images': image_codes, } return label, d
def allgens(line): r""" Parses one line from an allgens file. Returns the label and a dict containing fields with keys 'conductor', 'iso', 'number', 'ainvs', 'jinv', 'cm', 'rank', 'gens', 'torsion_order', 'torsion_structure', 'torsion_generators', all values being strings or ints. Input line fields: conductor iso number ainvs rank torsion_structure gens torsion_gens Sample input line: 20202 i 2 [1,0,0,-298389,54947169] 1 [2,4] [-570:6603:1] [-622:311:1] [834:19239:1] """ data = split(line) label = data[0] + data[1] + data[2] rank = int(data[4]) t = data[5] if t=='[]': t = [] else: t = [int(c) for c in t[1:-1].split(",")] torsion = int(prod([ti for ti in t], 1)) ainvs = parse_ainvs(data[3]) E = EllipticCurve([ZZ(a) for a in ainvs]) jinv = unicode(str(E.j_invariant())) if E.has_cm(): cm = int(E.cm_discriminant()) else: cm = int(0) content = { 'conductor': int(data[0]), 'iso': data[0] + data[1], 'number': int(data[2]), 'ainvs': ainvs, 'jinv': jinv, 'cm': cm, 'rank': int(data[4]), 'gens': ["(%s)" % gen[1:-1] for gen in data[6:6 + rank]], 'torsion': torsion, 'torsion_structure': ["%s" % tor for tor in t], 'torsion_generators': ["%s" % parse_tgens(tgens[1:-1]) for tgens in data[6 + rank:]], } extra_data = make_extra_data(label,content['number'],ainvs,content['gens']) content.update(extra_data) return label, content
def minimal_discriminant_ideal(E): r""" Return the minimal discriminant ideal of this elliptic curve. INPUT: - ``E`` -- an elliptic curve over a number field OUTPUT: The integral ideal D whose valuation at every prime P is that of the local minimal model for E at P. """ dat = E.local_data() return prod([d.prime() ** d.discriminant_valuation() for d in dat], E.base_field().ideal(1))
def get_T1(K, S, unit_first=True, verbose=False): # Sx is a list of generators of K(S,2) with the unit first or last, assuming h(K)=1 u = -1 if K==QQ else K(K.unit_group().torsion_generator()) from KSp import IdealGenerator Sx = [IdealGenerator(P) for P in S] if unit_first: Sx = [u] + Sx else: Sx = Sx + [u] r = len(Sx) N = prod(S,1) # Initialize T1 to be empty and A to be a matric with 0 rows and r=#Sx columns T1 = [] A = Matrix(GF(2),0,len(Sx)) primes = primes_iter(K,1) p = primes.next() # Repeat the following until A has full rank: take the next prime p # from the iterator, skip if it divides N (=product over S), form the # vector v, and keep p and append v to the bottom of A if it increases # the rank: while A.rank() < r: p = primes.next() while p.divides(N): p = primes.next() if verbose: print("A={} with {} rows and {} cols".format(A,A.nrows(),A.ncols())) v = vector(alphalist(p, Sx)) if verbose: print("v={}".format(v)) A1 = A.stack(v) if A1.rank() > A.rank(): A = A1 T1 = T1 + [p] if verbose: print("new A={} with {} rows and {} cols".format(A,A.nrows(),A.ncols())) print("T1 increases to {}".format(T1)) # the last thing returned is a "decoder" which returns the # discriminant Delta given the splitting beavious at the primes in # T1: B = A.inverse() def decoder(alphalist): e = list(B*vector(alphalist)) return prod([D**ZZ(ei) for D,ei in zip(Sx,e)], 1) return T1, A, decoder
def _find_limits_original(tau,gtau,level,v0): if tau.parent().is_exact(): p = v0.codomain().prime() else: p = tau.parent().prime() opt_evals = None opt_V = None for lmb,uu in find_lambda(gtau,p,n_results = 1): #verbose('trying lambda = %s, u = (-)p^%s'%(lmb,uu.valuation(p))) dec = decompose(gtau,lmb,uu) assert prod(dec) == gtau V,n_evals = get_limits_from_decomp(tau,dec,v0) # verbose('n_evals = %s'%n_evals) if opt_evals is None or n_evals < opt_evals: opt_V = V opt_evals = n_evals return opt_V
def JG_torsion_upperbound(G, bound = 60): """ INPUT: - G - a congruence subgroup - bound (optional, default = 60) - the bound for the primes p up to which to use the hecke matrix `T_p - <p> - p` for bounding the torsion subgroup OUTPUT: - A subgroup of `(S_2(G) \otimes \QQ) / S_2(G)` that is guaranteed to contain the rational torison subgroup, together with a subgroup generated by the rational cusps. The subgroup is given as a subgroup of `S_2(G)/NS_2(G)` for a suitable integer N EXAMPLES:: sage: from mdsage import * sage: d = rational_cuspidal_classgroup(Gamma1(23)).cardinality() sage: upper_bound_index_cusps_in_JG_torsion(Gamma1(23),d) 1 """ N = G.level() M=ModularSymbols(G); Sint=cuspidal_integral_structure(M) kill_mat=(M.star_involution().matrix().restrict(Sint)-1) kill=kill_mat.transpose().change_ring(ZZ).row_module() for p in prime_range(3,bound): if not N % p ==0: kill+=kill_torsion_coprime_to_q(p,M).restrict(Sint).change_ring(ZZ).transpose().row_module() #if kill.matrix().is_square() and kill.matrix().determinant()==d: # #print p # break kill_mat=kill.matrix().transpose() #print N,"index of torsion in stuff killed",kill.matrix().determinant()/d #if kill.matrix().determinant()==d: # return 1 d = prod(kill_mat.smith_form()[0].diagonal()) pm=integral_period_mapping(M) #period_images1=[sum([M.coordinate_vector(M([c,infinity])) for c in cusps])*pm for cusps in galois_orbits(G)] period_images2=[M.coordinate_vector(M([c,infinity]))*pm for c in G.cusps() if c != Cusp(oo)] m=(Matrix(period_images2)*kill_mat).stack(kill_mat) m,d2=m._clear_denom() d=gcd(d,d2)
def compute_dirichlet_series(p_list, PREC): ''' computes the dirichlet series for a Lfunction_SMF2_scalar_valued ''' # p_list is a list of pairs (p,y) where p is a prime and y is the list of roots of the Euler factor at x LL = [0] * PREC # create an empty list of the right size and now populate it with the powers of p for (p, y) in p_list: # FIXME p_prec is never used, but perhaps it should be? # p_prec = log(PREC) / log(p) + 1 ep = euler_p_factor(y, PREC) for n in range(ep.prec()): if p ** n < PREC: LL[p ** n] = ep.coefficients()[n] for i in range(1, PREC): f = factor(i) if len(f) > 1: # not a prime power LL[i] = prod([LL[p ** e] for (p, e) in f]) return LL[1:]
def get_T0(K,S, flist=None, verbose=False): # Compute all cubics unramified outside S if not supplied: if flist == None: from C2C3S3 import C3S3_extensions flist = C3S3_extensions(K,S) if verbose: print("cubics: {}".format(flist)) # Append the reducible cubic x = polygen(K) flist0 = flist + [x**3] n = len(flist) # Starting with no primes, compute the lambda matrix plist = [] vlist = [lamvec(f,plist) for f in flist0] ij = equal_vecs(vlist) if verbose: print("With plist={}, vlist={}, ij={}".format(plist,vlist,ij)); N = prod(S,1) # As long as the vectors in vlist are not all distinct, find two # indices i,j for which they are the same and find a new prime which # distinguishes these two, add it to the list and update: while ij: i,j = ij if j==n: p = get_p_1(K,flist[i],N) else: p = get_p_2(K,flist[i],flist[j],N) plist = plist + [p] if verbose: print("plist = {}".format(plist)) vlist = [lamvec(f,plist) for f in flist0] ij = equal_vecs(vlist) if verbose: print("With plist={}, vlist={}, ij={}".format(plist,vlist,ij)); vlist = vlist[:-1] # Sort the primes into order and recompute the vectors: plist.sort() vlist = [lamvec(f,plist) for f in flist] return flist, plist, vlist
def count_structure(n, sty="S1"): pat = S[sty] rows = [] for i in pat: if i==1: rows.append([(0,) + ((1,)*(n-2)) + (0,)]) elif i==0: rows.append([(0,)*i + (1,) + (0,)*(n-i-2) + (1,) for i in range(1, n-i-1)]) else: rows.append([(0,)+l for l in product([0,1], repeat=n-1) if l.count(1) > 1 and l.count(0) < n-2]) ret = [] proditer = ([p1,p2,p3] for p1,p2,p3 in product(*rows) if p1!=p2 and p2!=p3 and p1!=p3) for M in ProgressBar(maxval=prod(map(len, rows)))(imap(matrix, proditer)): if not any(S in ret for S in row_orbit(M)): ret.append(M) return ret
def make_bsd(self): bsd = self.bsd = {} r = self.rank if r >= 2: bsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r,r) elif r: bsd['lder_name'] = "L'(E,1)" else: bsd['lder_name'] = "L(E,1)" bsd['reg'] = self.regulator bsd['omega'] = self.real_period bsd['sha'] = self.sha bsd['lder'] = self.special_value tamagawa_numbers = [ZZ(_ld['cp']) for _ld in self.local_data] cp_fac = [cp.factor() for cp in tamagawa_numbers] cp_fac = [latex(cp) if len(cp)<2 else '('+latex(cp)+')' for cp in cp_fac] bsd['tamagawa_factors'] = r'\cdot'.join(cp_fac) bsd['tamagawa_product'] = prod(tamagawa_numbers)