def __init__(self, group, dchar=(1, 1), dual=False, is_trivial=False, dimension=1, **kwargs): r""" if dual is set to true we use the complex conjugate of the representation (we assume the representation is unitary) The pair dchar = (conductor,number) gives the character in conrey numbering If char_nr = -1 = > kronecker_character If char_nr = -2 = > kronecker_character_upside_down """ self._group = group if not hasattr(self, '_weight'): self._weight = None self._dim = dimension self._ambient_rank = kwargs.get('ambient_rank', None) self._kwargs = kwargs self._verbose = kwargs.get("verbose", 0) if self._verbose > 0: print("Init multiplier system!") (conductor, char_nr) = dchar self._conductor = conductor self._char_nr = char_nr self._character = None self._level = group.generalised_level() if 'character' in kwargs: if str(type(kwargs['character'])).find('Dirichlet') >= 0: self._character = kwargs['character'] self._conductor = self._character.conductor() try: self._char_nr = self._character.number() except: for x in DirichletGroup_conrey(self._conductor): if x.sage_character() == self._character: self._char_nr = x.number() elif group.is_congruence(): if conductor <= 0: self._conductor = group.level() self._char_nr = 1 if char_nr >= 0: self._char_nr = char_nr if self._char_nr == 0 or self._char_nr == 1: self._character = trivial_character(self._conductor) elif self._char_nr == -1: if self._conductor % 4 == 3: self._character = kronecker_character(-self._conductor) elif self._conductor % 4 == 1: self._character = kronecker_character(self._conductor) assert self._character.conductor() == self._conductor elif self._char_nr <= -2: self._character = kronecker_character_upside_down( self._conductor) else: self._character = DirichletCharacter_conrey( DirichletGroup_conrey(self._conductor), self._char_nr).sage_character() else: self._conductor = 1 self._character = trivial_character(1) #if not hasattr(self._character,'is_trivial'): # if isinstance(self._character,(int,Integer)) and group.is_congruence(): # j = self._character # self._character = DirichletGroup(group.level())[j] ## Extract the class name for the reduce algorithm self._class_name = str(type(self))[1:-2].split(".")[-1] if not isinstance(dimension, (int, Integer)): raise ValueError("Dimension must be integer!") self._is_dual = dual self._is_trivial = is_trivial and self._character.is_trivial() if is_trivial and self._character.order() <= 2: self._is_real = True else: self._is_real = False self._character_values = [] ## Store for easy access
def __init__(self,group,dchar=(1,1),dual=False,is_trivial=False,dimension=1,**kwargs): r""" if dual is set to true we use the complex conjugate of the representation (we assume the representation is unitary) The pair dchar = (conductor,number) gives the character in conrey numbering If char_nr = -1 = > kronecker_character If char_nr = -2 = > kronecker_character_upside_down """ #print "kwargs0=",kwargs self._group = group self._weight = None self._dim = dimension self._ambient_rank=kwargs.get('ambient_rank',None) self._kwargs = kwargs self._verbose = kwargs.get("verbose",0) if self._verbose>0: print "Init multiplier system!" (conductor,char_nr)=dchar self._conductor=conductor self._char_nr=char_nr self._character = None self._level = group.generalised_level() if kwargs.has_key('character'): if str(type(kwargs['character'])).find('Dirichlet')>=0: self._character = kwargs['character'] self._conductor=self._character.conductor() try: self._char_nr=self._character.number() except: for x in DirichletGroup_conrey(self._conductor): if x.sage_character() == self._character: self._char_nr=x.number() elif group.is_congruence(): if conductor<=0: self._conductor=group.level(); self._char_nr=1 if char_nr>=0: self._char_nr=char_nr if self._char_nr==0 or self._char_nr==1: self._character = trivial_character(self._conductor) elif self._char_nr==-1: if self._conductor % 4 == 3: self._character = kronecker_character(-self._conductor) elif self._conductor % 4 == 1: self._character = kronecker_character(self._conductor) assert self._character.conductor()==self._conductor elif self._char_nr<=-2: self._character = kronecker_character_upside_down(self._conductor) else: self._character = DirichletCharacter_conrey(DirichletGroup_conrey(self._conductor),self._char_nr).sage_character() else: self._conductor = 1 self._character = trivial_character(1) #if not hasattr(self._character,'is_trivial'): # if isinstance(self._character,(int,Integer)) and group.is_congruence(): # j = self._character # self._character = DirichletGroup(group.level())[j] ## Extract the class name for the reduce algorithm self._class_name=str(type(self))[1:-2].split(".")[-1] if not isinstance(dimension,(int,Integer)): raise ValueError,"Dimension must be integer!" self._is_dual = dual self._is_trivial=is_trivial and self._character.is_trivial() if is_trivial and self._character.order()<=2: self._is_real=True else: self._is_real=False self._character_values = [] ## Store for easy access
class MultiplierSystem(SageObject): r""" Base class for multiplier systems. A multiplier system is a function: v : Gamma - > C^dim s.t. there exists a merom. function of weight k f:H->C^dim with f|A=v(A)f """ def __init__(self, group, dchar=(1, 1), dual=False, is_trivial=False, dimension=1, **kwargs): r""" if dual is set to true we use the complex conjugate of the representation (we assume the representation is unitary) The pair dchar = (conductor,number) gives the character in conrey numbering If char_nr = -1 = > kronecker_character If char_nr = -2 = > kronecker_character_upside_down """ self._group = group if not hasattr(self, '_weight'): self._weight = None self._dim = dimension self._ambient_rank = kwargs.get('ambient_rank', None) self._kwargs = kwargs self._verbose = kwargs.get("verbose", 0) if self._verbose > 0: print("Init multiplier system!") (conductor, char_nr) = dchar self._conductor = conductor self._char_nr = char_nr self._character = None self._level = group.generalised_level() if 'character' in kwargs: if str(type(kwargs['character'])).find('Dirichlet') >= 0: self._character = kwargs['character'] self._conductor = self._character.conductor() try: self._char_nr = self._character.number() except: for x in DirichletGroup_conrey(self._conductor): if x.sage_character() == self._character: self._char_nr = x.number() elif group.is_congruence(): if conductor <= 0: self._conductor = group.level() self._char_nr = 1 if char_nr >= 0: self._char_nr = char_nr if self._char_nr == 0 or self._char_nr == 1: self._character = trivial_character(self._conductor) elif self._char_nr == -1: if self._conductor % 4 == 3: self._character = kronecker_character(-self._conductor) elif self._conductor % 4 == 1: self._character = kronecker_character(self._conductor) assert self._character.conductor() == self._conductor elif self._char_nr <= -2: self._character = kronecker_character_upside_down( self._conductor) else: self._character = DirichletCharacter_conrey( DirichletGroup_conrey(self._conductor), self._char_nr).sage_character() else: self._conductor = 1 self._character = trivial_character(1) #if not hasattr(self._character,'is_trivial'): # if isinstance(self._character,(int,Integer)) and group.is_congruence(): # j = self._character # self._character = DirichletGroup(group.level())[j] ## Extract the class name for the reduce algorithm self._class_name = str(type(self))[1:-2].split(".")[-1] if not isinstance(dimension, (int, Integer)): raise ValueError("Dimension must be integer!") self._is_dual = dual self._is_trivial = is_trivial and self._character.is_trivial() if is_trivial and self._character.order() <= 2: self._is_real = True else: self._is_real = False self._character_values = [] ## Store for easy access def __getinitargs__(self): #print "get initargs" return (self._group, (self._conductor, self._char_nr), self._is_dual, self._is_trivial, self._dim) def __reduce__(self): #print "reduce!" t = self.__getinitargs__() return self.__class__, t #return(TrivialMultiplier,(self._group,self._dim,(self._conductor,self._char_nr),self._is_dual,self._is_trivial)) # return(type(self),(self._group,self._dim,(self._conductor,self._char_nr),self._is_dual,self._is_trivial)) def dual_multiplier(self): r""" Returns the dual multiplier of self. """ m = copy(self) m._is_dual = int(not self._is_dual) o = self._character.order() m._character = self._character**(o - 1) m._weight = QQ(2) - QQ(self.weight()) return m def __repr__(self): r""" Needs to be defined in subclasses. """ raise NotImplementedError def group(self): return self._group def is_dual(self): return int(self._is_dual) def level(self): return self._level def weight(self): r""" Return (modulo 2) which weight self is a multiplier system consistent with """ if self._is_trivial: self._weight = 0 return self._weight if self._dim == 1: if self._weight is None: Z = SL2Z([-1, 0, 0, -1]) v = self._action(Z) if v == 1: self._weight = QQ(0) if v == -1: self._weight = QQ(1) elif v == -I: self._weight = QQ(1) / QQ(2) elif v == I: self._weight = QQ(1) / QQ(2) else: raise NotImplementedError return self._weight def __call__(self, A): r""" For eficientcy we should also allow to act on lists """ if isinstance(A, (ArithmeticSubgroupElement, SL2Z_elt, list)): if A not in self._group: raise ValueError("Element {0} is not in {1}! ".format( A, self._group)) return self._action(A) else: raise NotImplementedError( "Do not know how the multiplier should act on {0}".format(A)) def _action(self): raise NotImplementedError(" Needs to be overridden by subclasses!") def is_trivial(self): return self._is_trivial def is_real(self): return self._is_real def set_dual(self): self._is_dual = True #not self._is_dual def character(self): return self._character def weil_module(self): if hasattr(self, "_weil_module"): if self._verbose > 1: print("self has weil_module!") return self._weil_module return None def rank(self): return self._dim def ambient_rank(self): r""" Return the dimension of the unsymmetrized space containing self. """ if self._ambient_rank != None: return self._ambient_rank else: return self._dim def __eq__(self, other): r""" A character is determined by the group it is acting on and its type, which is given by the representation. """ if str(type(other)).find('Multiplier') < 0: return False if self._group != other._group: return False if self._dim != other._dim: return False return self.__repr__() == other.__repr__() def __ne__(self, other): return not self.__eq__(other) def is_consistent(self, k): r""" Checks that v(-I)=(-1)^k, """ Z = SL2Z([-1, 0, 0, -1]) zi = CyclotomicField(4).gen() v = self._action(Z) if self._verbose > 0: print("test consistency for k={0}".format(k)) print("v(Z)={0}".format(v)) if self._dim == 1: if isinstance(k, Integer) or k.is_integral(): if is_even(k): v1 = ZZ(1) else: v1 = ZZ(-1) elif isinstance(k, Rational) and (k.denominator() == 2 or k == 0): v1 = zi**(-QQ(2 * k)) if self._verbose > 0: print("I**(-2k)={0}".format(v1)) else: raise ValueError( "Only integral and half-integral weight is currently supported! Got weight:{0} of type:{1}" .format(k, type(k))) else: raise NotImplementedError( "Override this function for vector-valued multipliers!") return v1 == v
class MultiplierSystem(SageObject): r""" Base class for multiplier systems. A multiplier system is a function: v : Gamma - > C^dim s.t. there exists a merom. function of weight k f:H->C^dim with f|A=v(A)f """ def __init__(self,group,dchar=(1,1),dual=False,is_trivial=False,dimension=1,**kwargs): r""" if dual is set to true we use the complex conjugate of the representation (we assume the representation is unitary) The pair dchar = (conductor,number) gives the character in conrey numbering If char_nr = -1 = > kronecker_character If char_nr = -2 = > kronecker_character_upside_down """ #print "kwargs0=",kwargs self._group = group self._weight = None self._dim = dimension self._ambient_rank=kwargs.get('ambient_rank',None) self._kwargs = kwargs self._verbose = kwargs.get("verbose",0) if self._verbose>0: print "Init multiplier system!" (conductor,char_nr)=dchar self._conductor=conductor self._char_nr=char_nr self._character = None self._level = group.generalised_level() if kwargs.has_key('character'): if str(type(kwargs['character'])).find('Dirichlet')>=0: self._character = kwargs['character'] self._conductor=self._character.conductor() try: self._char_nr=self._character.number() except: for x in DirichletGroup_conrey(self._conductor): if x.sage_character() == self._character: self._char_nr=x.number() elif group.is_congruence(): if conductor<=0: self._conductor=group.level(); self._char_nr=1 if char_nr>=0: self._char_nr=char_nr if self._char_nr==0 or self._char_nr==1: self._character = trivial_character(self._conductor) elif self._char_nr==-1: if self._conductor % 4 == 3: self._character = kronecker_character(-self._conductor) elif self._conductor % 4 == 1: self._character = kronecker_character(self._conductor) assert self._character.conductor()==self._conductor elif self._char_nr<=-2: self._character = kronecker_character_upside_down(self._conductor) else: self._character = DirichletCharacter_conrey(DirichletGroup_conrey(self._conductor),self._char_nr).sage_character() else: self._conductor = 1 self._character = trivial_character(1) #if not hasattr(self._character,'is_trivial'): # if isinstance(self._character,(int,Integer)) and group.is_congruence(): # j = self._character # self._character = DirichletGroup(group.level())[j] ## Extract the class name for the reduce algorithm self._class_name=str(type(self))[1:-2].split(".")[-1] if not isinstance(dimension,(int,Integer)): raise ValueError,"Dimension must be integer!" self._is_dual = dual self._is_trivial=is_trivial and self._character.is_trivial() if is_trivial and self._character.order()<=2: self._is_real=True else: self._is_real=False self._character_values = [] ## Store for easy access def __getinitargs__(self): #print "get initargs" return (self._group,(self._conductor,self._char_nr),self._is_dual,self._is_trivial,self._dim) def __reduce__(self): #print "reduce!" t = self.__getinitargs__() return self.__class__,t #return(TrivialMultiplier,(self._group,self._dim,(self._conductor,self._char_nr),self._is_dual,self._is_trivial)) # return(type(self),(self._group,self._dim,(self._conductor,self._char_nr),self._is_dual,self._is_trivial)) def dual_multiplier(self): r""" Returns the dual multiplier of self. """ m = copy(self) m._is_dual = int(not self._is_dual) o = self._character.order() m._character = self._character**(o-1) m._weight = QQ(2) - QQ(self.weight()) return m def __repr__(self): r""" Needs to be defined in subclasses. """ raise NotImplementedError def group(self): return self._group def is_dual(self): return int(self._is_dual) def level(self): return self._level def weight(self): r""" Return (modulo 2) whish weight self is a multiplier system consistent with """ if self._is_trivial: self._weight = 0 return self._weight if self._dim == 1: if self._weight is None: Z=SL2Z([-1,0,0,-1]) v = self._action(Z) if v == 1: self._weight = QQ(0) if v == -1: self._weight = QQ(1) elif v == -I: self._weight = QQ(1)/QQ(2) elif v == I: self._weight = QQ(1)/QQ(2) else: raise NotImplementedError return self._weight def __call__(self,A): r""" For eficientcy we should also allow to act on lists """ if isinstance(A,(ArithmeticSubgroupElement,SL2Z_elt,list)): if A not in self._group: raise ValueError,"Element %s is not in %s! " %(A,self._group) return self._action(A) else: raise NotImplementedError,"Do not know how the multiplier should act on {0}".format(A) def _action(self): raise NotImplemented," Needs to be overridden by subclasses!" def is_trivial(self): return self._is_trivial def is_real(self): return self._is_real def set_dual(self): self._is_dual = True #not self._is_dual def character(self): return self._character def weil_module(self): if hasattr(self,"_weil_module"): if self._verbose>1: print "self has weil_module!" return self._weil_module return None def rank(self): return self._dim def ambient_rank(self): r""" Return the dimension of the unsymmetrized space containing self. """ if self._ambient_rank<>None: return self._ambient_rank else: return self._dim def __eq__(self,other): r""" A character is determined by the group it is acting on and its type, which is given by the representation. """ if str(type(other)).find('Multiplier')<0: return False if self._group<>other._group: return False if self._dim<>other._dim: return False return self.__repr__()==other.__repr__() def __ne__(self,other): return not self.__eq__(other) def is_consistent(self,k): r""" Checks that v(-I)=(-1)^k, """ Z=SL2Z([-1,0,0,-1]) zi=CyclotomicField(4).gen() v = self._action(Z) if self._verbose>0: print "test consistency for k=",k print "v(Z)=",v if self._dim==1: if isinstance(k,Integer) or k.is_integral(): if is_even(k): v1 = ZZ(1) else: v1 = ZZ(-1) elif isinstance(k,Rational) and (k.denominator()==2 or k==0): v1 = zi**(-QQ(2*k)) if self._verbose>0: print "I**(-2k)=",v1 else: raise ValueError,"Only integral and half-integral weight is currently supported! Got weight:{0} of type:{1}".format(k,type(k)) else: raise NotImplemented,"Override this function for vector-valued multipliers!" return v1==v