def _compute(self): self.k = self.label2nf(self.nflabel) self._modulus = self.label2ideal(self.k, self.modlabel) self.G = RayClassGroup(self.k, self._modulus) self.H = self.G.dual_group() #self.number = lmfdb_label2hecke(self.numlabel) # make this canonical self.modlabel = self.ideal2label(self._modulus) self.credit = "Pari, SageMath" self.codelangs = ('pari', 'sage') self.parity = None logger.debug('###### WebHeckeComputed')
class WebHecke(WebCharObject): """ FIXME design issue: should underlying group elements be represented by tuples or by representative ideals ? for computations tuples are much better, this is also more compact. """ def _compute(self): self.k = self.label2nf(self.nflabel) self._modulus = self.label2ideal(self.k, self.modlabel) self.G = RayClassGroup(self.k, self._modulus) self.H = self.G.dual_group() #self.number = lmfdb_label2hecke(self.numlabel) # make this canonical self.modlabel = self.ideal2label(self._modulus) self.credit = "Pari, SageMath" self.codelangs = ('pari', 'sage') self.parity = None logger.debug('###### WebHeckeComputed') @property def generators(self): """ use representative ideals """ return self.textuple( map(self.ideal2tex, self.G.gen_ideals() ), tag=False ) """ labeling conventions are put here """ @staticmethod def char2tex(c, val='\cdot',tag=True): """ c is a Hecke character """ number = ','.join(map(str,c.exponents())) s = r'\chi_{%s}(%s)'%(number,val) if tag: return r'\(%s\)'%s else: return s def _char_desc(self, c, modlabel=None, prim=None): """ c is a Hecke character of modulus self.modulus unless modlabel is specified """ if modlabel == None: modlabel = self.modlabel numlabel = self.number2label( c.exponents() ) if prim == None: prim = c.is_primitive() return (modlabel, numlabel, self.char2tex(c), prim ) @staticmethod def ideal2tex(ideal): a,b = ideal.gens_two() return "\(\langle %s, %s\\rangle\)"%(a._latex_(), b._latex_()) @staticmethod def ideal2label(ideal): """ labeling convention for ideal f: use two elements representation f = (n,b) with n = f cap Z an integer and b an algebraic element sum b_i a^i label f as n.b1+b2*a^2+...bn*a^n (dot between n and b, a is the field generator, use '+' and ) """ a,b = ideal.gens_two() s = '+'.join( '%sa%i'%(b,i) for i,b in enumerate(b.polynomial().list()) if b != 0 ) return "%s.%s"%(a,s.replace('+-','-').replace('/','o')) @staticmethod def label2ideal(k,label): """ k = underlying number field """ if label.count('.'): n, b = label.split(".") else: n, b = label, '0' a = k.gen() # FIXME: dangerous n, b = evalpolelt(n,a,'a'), evalpolelt(b,a,'a') n, b = k(n), k(b) return k.ideal( (n,b) ) """ underlying group contains ideal classes, but are represented as exponent tuples on cyclic components (not canonical, but more compact) """ #group2tex = ideal2tex #group2label = ideal2label #label2group = label2ideal @staticmethod def group2tex(x, tag=True): if not isinstance(x, tuple): x = x.exponents() #s = '\cdot '.join('g_{%i}^{%i}'%(i,e) for i,e in enumerate(x) if e>0) s = [] for i,e in enumerate(x): if e > 0: if e==1: s.append('g_{%i}'%i) else: s.append('g_{%i}^{%i}'%(i,e)) s = '\cdot '.join(s) if s == '': s = '1' if tag: s = '\(%s\)'%s return s @staticmethod def group2label(self,x): return self.number2label(x.exponents()) def label2group(self,x): """ x is either an element of k or a tuple of ints or an ideal """ if x.count('.'): x = self.label2ideal(self.k,x) elif x.count('a'): a = self.k.gen() x = evalpolelt(x,a,'a') elif x.count(','): x = tuple(map(int,x.split(','))) return self.G(x) @staticmethod def number2label(number): return '.'.join(map(str,number)) @staticmethod def label2number(label): return map(int,label.split('.')) @staticmethod def label2nf(label): return WebNumberField(label).K() # FIXME: replace by calls to WebNF #x = var('x') #pol = evalpolelt(label,x,'x') #return NumberField(pol,'a') @property def groupelts(self): return map(self.group2tex, self.Gelts()) @cached_method def Gelts(self): res = [] c = 1 for x in self.G.iter_exponents(): res.append(x) c += 1 if c > self.maxcols: self.coltruncate = True break return res
def chargroup(self, mod): return RayClassGroup(self.k, mod).dual_group()
class WebHecke(WebCharObject): """ FIXME design issue: should underlying group elements be represented by tuples or by representative ideals ? for computations tuples are much better, this is also more compact. """ def _compute(self): self.k = self.label2nf(self.nflabel) self._modulus = self.label2ideal(self.k, self.modlabel) self.G = RayClassGroup(self.k, self._modulus) self.H = self.G.dual_group() #self.number = lmfdb_label2hecke(self.numlabel) # make this canonical self.modlabel = self.ideal2label(self._modulus) self.credit = "Pari, SageMath" self.codelangs = ('pari', 'sage') self.parity = None logger.debug('###### WebHeckeComputed') @property def generators(self): """ use representative ideals """ return self.textuple(map(self.ideal2tex, self.G.gen_ideals()), tag=False) """ labeling conventions are put here """ @staticmethod def char2tex(c, val='\cdot', tag=True): """ c is a Hecke character """ number = ','.join(map(str, c.exponents())) s = r'\chi_{%s}(%s)' % (number, val) if tag: return r'\(%s\)' % s else: return s def _char_desc(self, c, modlabel=None, prim=None): """ c is a Hecke character of modulus self.modulus unless modlabel is specified """ if modlabel == None: modlabel = self.modlabel numlabel = self.number2label(c.exponents()) if prim == None: prim = c.is_primitive() return (modlabel, numlabel, self.char2tex(c), prim) @staticmethod def ideal2tex(ideal): a, b = ideal.gens_two() return "\(\langle %s, %s\\rangle\)" % (a._latex_(), b._latex_()) @staticmethod def ideal2label(ideal): """ labeling convention for ideal f: use two elements representation f = (n,b) with n = f cap Z an integer and b an algebraic element sum b_i a^i label f as n.b1+b2*a^2+...bn*a^n (dot between n and b, a is the field generator, use '+' and ) """ a, b = ideal.gens_two() s = '+'.join('%sa%i' % (b, i) for i, b in enumerate(b.polynomial().list()) if b != 0) return "%s.%s" % (a, s.replace('+-', '-').replace('/', 'o')) @staticmethod def label2ideal(k, label): """ k = underlying number field """ if label.count('.'): n, b = label.split(".") else: n, b = label, '0' a = k.gen() # FIXME: dangerous n, b = evalpolelt(n, a, 'a'), evalpolelt(b, a, 'a') n, b = k(n), k(b) return k.ideal((n, b)) """ underlying group contains ideal classes, but are represented as exponent tuples on cyclic components (not canonical, but more compact) """ #group2tex = ideal2tex #group2label = ideal2label #label2group = label2ideal @staticmethod def group2tex(x, tag=True): if not isinstance(x, tuple): x = x.exponents() #s = '\cdot '.join('g_{%i}^{%i}'%(i,e) for i,e in enumerate(x) if e>0) s = [] for i, e in enumerate(x): if e > 0: if e == 1: s.append('g_{%i}' % i) else: s.append('g_{%i}^{%i}' % (i, e)) s = '\cdot '.join(s) if s == '': s = '1' if tag: s = '\(%s\)' % s return s @staticmethod def group2label(self, x): return self.number2label(x.exponents()) def label2group(self, x): """ x is either an element of k or a tuple of ints or an ideal """ if x.count('.'): x = self.label2ideal(self.k, x) elif x.count('a'): a = self.k.gen() x = evalpolelt(x, a, 'a') elif x.count(','): x = tuple(map(int, x.split(','))) return self.G(x) @staticmethod def number2label(number): return '.'.join(map(str, number)) @staticmethod def label2number(label): return map(int, label.split('.')) @staticmethod def label2nf(label): return WebNumberField(label).K() # FIXME: replace by calls to WebNF #x = var('x') #pol = evalpolelt(label,x,'x') #return NumberField(pol,'a') @property def groupelts(self): return map(self.group2tex, self.Gelts()) @cached_method def Gelts(self): res = [] c = 1 for x in self.G.iter_exponents(): res.append(x) c += 1 if c > self.maxcols: self.coltruncate = True break return res