def compute_all_icosians(): """ Return a list of the elements of the Icosian group of order 120, which we compute by generating enough products of icosian generators. EXAMPLES:: sage: from psage.modform.hilbert.sqrt5.sqrt5 import compute_all_icosians, all_icosians sage: v = compute_all_icosians() sage: len(v) 120 sage: v [1/2 + 1/2*a*i + (-1/2*a + 1/2)*k, 1/2 + (-1/2*a + 1/2)*i + 1/2*a*j,..., -k, i, j, -i] sage: assert set(v) == set(all_icosians()) # double check """ from sage.all import permutations, cartesian_product_iterator Icos = [] ig = icosian_gens() per = permutations(range(5)) exp = cartesian_product_iterator([range(1, i) for i in [5, 5, 5, 4, 5]]) for f in exp: for p in per: e0 = ig[p[0]]**f[0] e1 = ig[p[1]]**f[1] e2 = ig[p[2]]**f[2] e3 = ig[p[3]]**f[3] e4 = ig[p[4]]**f[4] elt = e0 * e1 * e2 * e3 * e4 if elt not in Icos: Icos.append(elt) if len(Icos) == 120: return Icos
def collapse_to_labels_and_exps(self): # before calling this function, must collapse stars # only exponent None is collapsable collapsable_labels = defaultdict(lambda:defaultdict(int)) collapsable_dims = defaultdict(int) # label unspecified # the following lists will store pieces with specified exponent fixed_labels = defaultdict(lambda:defaultdict(int)) fixed_dims = defaultdict(list) for piece in self.L: if piece.e is None: if piece.label is None: collapsable_dims[piece.dim] += 1 else: collapsable_labels[piece.dim][piece.label] += 1 # allow for repeated labels else: if piece.label is None: fixed_dims[piece.dim].append(piece.e) else: fixed_labels[piece.dim][piece.label] += piece.e # allow for repeated labels dims = sorted(list(set(piece.dim for piece in self.L))) iterator_list = [CollapsedLabelIterator_onedim(collapsable_labels[dim], collapsable_dims[dim], fixed_labels[dim], fixed_dims[dim], dim, self.q()) for dim in dims] for stretches in cartesian_product_iterator(iterator_list): subquery = {} self.OC.inc() overall = sum(stretches, []) for i, (base, exp) in enumerate(overall): subquery['%s.%s.0'%(self.qfield, i)] = base subquery['%s.%s.1'%(self.qfield, i)] = int(exp) subquery[self.qfield] = {'$size': len(overall)} yield subquery
def hecke_elements_2(): P = F.primes_above(2)[0] from sqrt5_fast import ModN_Reduction from sage.matrix.all import matrix f = ModN_Reduction(P) G = icosian_ring_gens() k = P.residue_field() g = k.gen() def pi(z): # Note that f(...) returns a string right now, since it's all done at C level. # This will prboably change, breaking this code. M = matrix(k, 2, eval(f(z).replace(';', ','), {'g': g})).transpose() v = M.echelon_form()[0] v.set_immutable() return v # now just run through elements of icosian ring until we find enough... ans = {} a = F.gen() B = 1 X = [i + a * j for i in range(-B, B + 1) for j in range(-B, B + 1)] from sage.misc.all import cartesian_product_iterator for v in cartesian_product_iterator([X] * 4): z = sum(v[i] * G[i] for i in range(4)) if z.reduced_norm() == 2: t = pi(z) if not ans.has_key(t): ans[t] = z if len(ans) == 5: return [x for _, x in ans.iteritems()] raise RuntimeError
def compute_all_icosians(): """ Return a list of the elements of the Icosian group of order 120, which we compute by generating enough products of icosian generators. EXAMPLES:: sage: from sage.modular.hilbert.sqrt5 import compute_all_icosians, all_icosians sage: v = compute_all_icosians() sage: len(v) 120 sage: v [1/2 + 1/2*a*i + (-1/2*a + 1/2)*k, 1/2 + (-1/2*a + 1/2)*i + 1/2*a*j,..., -k, i, j, -i] sage: assert set(v) == set(all_icosians()) # double check """ from sage.all import permutations, cartesian_product_iterator Icos = [] ig = icosian_gens() per = permutations(range(5)) exp = cartesian_product_iterator([range(1,i) for i in [5,5,5,4,5]]) for f in exp: for p in per: e0 = ig[p[0]]**f[0] e1 = ig[p[1]]**f[1] e2 = ig[p[2]]**f[2] e3 = ig[p[3]]**f[3] e4 = ig[p[4]]**f[4] elt = e0*e1*e2*e3*e4 if elt not in Icos: Icos.append(elt) if len(Icos) == 120: return Icos
def hecke_elements_2(): P = F.primes_above(2)[0] from sqrt5_fast import ModN_Reduction from sage.matrix.all import matrix f = ModN_Reduction(P) G = icosian_ring_gens() k = P.residue_field() g = k.gen() def pi(z): # Note that f(...) returns a string right now, since it's all done at C level. # This will prboably change, breaking this code. M = matrix(k,2,eval(f(z).replace(';',','), {'g':g})).transpose() v = M.echelon_form()[0] v.set_immutable() return v # now just run through elements of icosian ring until we find enough... ans = {} a = F.gen() B = 1 X = [i + a*j for i in range(-B,B+1) for j in range(-B,B+1)] from sage.misc.all import cartesian_product_iterator for v in cartesian_product_iterator([X]*4): z = sum(v[i]*G[i] for i in range(4)) if z.reduced_norm() == 2: t = pi(z) if not ans.has_key(t): ans[t] = z if len(ans) == 5: return [x for _, x in ans.iteritems()] raise RuntimeError
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 ALdims_knowl(al_dims, level, weight): dim_dict = {} for vec, dim, cnt in al_dims: dim_dict[tuple(ev for (p, ev) in vec)] = dim short = "+".join(r'\(%s\)' % dim_dict.get(vec, 0) for vec in cartesian_product_iterator( [[1, -1] for _ in range(len(al_dims[0][0]))])) # We erase plus_dim and minus_dim if they're obvious AL_table = ALdim_table(al_dims, level, weight) return r'<a title="[ALdims]" knowl="dynamic_show" kwargs="%s">%s</a>' % ( AL_table, short)
def points(self): """ The vertices in a fixed order (lexicographic sorted) EXAMPLES:: sage: square = UnitCubeTriangulation(2) sage: square.points() ((0, 0), (0, 1), (1, 0), (1, 1)) """ return tuple( sorted( tuple(p) for p in cartesian_product_iterator([[0, 1]] * self.dimension)))
def points(self): """ The vertices in a fixed order (lexicographic sorted) EXAMPLES:: sage: square = CubeTriangulation((1,2), (3,2), (1,4), (3,4)) sage: square.points() ((1, 2), (1, 4), (3, 2), (3, 4)) """ return tuple( sorted( tuple(p) for p in cartesian_product_iterator( zip(self.extent_min, self.extent_max))))
def compute_lseries(s, f, prec, T=1.05): """ s = session f = rational newform object (got using the session s!) prec = bits of precision This function computes the L-series attached to the given newform and determine the a_p at the primes of bad reduction (up to the biggest p such that a_p is known) if they are not known, and saves those a_p in the database. It uses prec bits of precision, and if not enough a_p are known in the database, then it will fail. DOES NOT COMMIT. Call s.commit() after calling this to save. """ # # 1. Get list of primes and the corresponding known a_P (for all P # up to some bound): # - query for biggest Norm(P) so we know a_P (separate function) # - get list of all primes q with Norm(q) <= Norm(P). # - make another list of primes q such that q exactly divides level # - query database and get corresponding good a_q, or raise # error if some missing. # Compute aplist: # - aplist = list of integers of None # - primes = list of psage fast primes # - unknown = list of ints i such that ap[i] = None aplist, primes = f.known_aplist() unknown = [i for i in range(len(aplist)) if aplist[i] is None] # Check that the unknown primes all exactly divide the level. level = f.level() for i in unknown: P = primes[i].sage_ideal() if not P.divides(level): raise RuntimeError, "gap in list of eigenvalues a_P; missing good P=%s"%P if (P*P).divides(level): raise RuntimeError, "gap: additive a_P for P=%s not set"%P # 2. For each possibility for bad a_P, construct the L-series, # making a list of the L-series that actually work. # - use cartesian product iterator over [[-1,1]]*n # - we use a custom L-series class deriving from what # is in psage defined above lseries_that_work = [] for bad_ap in cartesian_product_iterator([[-1,1]]*len(unknown)): print "bad_ap = ", bad_ap aplist1 = list(aplist) for i, j in enumerate(unknown): aplist1[j] = bad_ap[i] for eps in [-1,1]: print "trying eps = ", eps L = LSeries(level=level, aplist=aplist1, primes=primes, prec=prec, root_number=eps) try: L._function(prec=prec, T=T) except RuntimeError: print "Definitely does not satisfy functional equation..." else: print "It seems to satisfy functional equation..." lseries_that_work.append((L, bad_ap)) if len(lseries_that_work) > 1: print "WARNING: %s choices of bad a_p's seem to work -- functional equation doesn't nail down one choice.\nWe will check numerically that all choices are consistent, and only save a_p that we are certain about."%len(lseries_that_work) if len(lseries_that_work) == 0: raise RuntimeError, "no choices of bad a_p's seem to work -- please increase precision!" # 3. If *exactly one* L-series works, save to the database the # corresponding bad a_p, and return the L-series. Otherwise, # raise an error. # Only save bad_ap's that are the same for all L-series. # save missing a_p, which we now know, to the database print "saving missing eigenvalues, which we just determined, to the database..." for i, j in enumerate(unknown): # only store ones such that multiple distinct choices didn't work. if len([bad_ap[i] for _, bad_ap in lseries_that_work]) == 1: f.store_eigenvalue(primes[j], lseries_that_work[0][1][i]) # return one of the L-series, after doing a double check that they are # all basically the same numerically. if len(lseries_that_work) > 1: ts = lseries_that_work[0][0].taylor_series(prec=prec) for i in range(1, len(lseries_that_work)): ts2 = lseries_that_work[i][0].taylor_series(prec=prec) if ts != ts2: raise RuntimeError, "ts=%s, ts2=%s"%(ts, ts2) L = lseries_that_work[0][0] # store epsilon factor (sign of f.e.) to the database if f.root_number is None: root_number = L.epsilon() print "saving root number (=%s) to database..."%root_number f.root_number = root_number f.root_number_prec = root_number_prec if f.rank is None: rank = L.analytic_rank(prec=prec) print "saving rank (=%s) to database..."%rank f.rank = rank f.rank_prec = prec return L