def is_subgroup(self, other): r""" Return True if self is a subgroup of right, and False otherwise. EXAMPLES:: sage: GammaH(24,[7]).is_subgroup(SL2Z) True sage: GammaH(24,[7]).is_subgroup(Gamma0(8)) True sage: GammaH(24, []).is_subgroup(GammaH(24, [7])) True sage: GammaH(24, []).is_subgroup(Gamma1(24)) True sage: GammaH(24, [17]).is_subgroup(GammaH(24, [7])) False sage: GammaH(1371, [169]).is_subgroup(GammaH(457, [169])) True """ from all import is_Gamma0, is_Gamma1 if not isinstance(other, GammaH_class): raise NotImplementedError # level of self should divide level of other if self.level() % other.level(): return False # easy cases if is_Gamma0(other): return True # recall self is a GammaH, so it's contained in Gamma0 if is_Gamma1(other) and len(self._generators_for_H()) > 0: return False else: # difficult case t = other._list_of_elements_in_H() for x in self._generators_for_H(): if not (x in t): return False return True
def __cmp__(self, other): """ Compare self to other. The ordering on congruence subgroups of the form GammaH(N) for some H is first by level and then by the subgroup H. In particular, this means that we have Gamma1(N) < GammaH(N) < Gamma0(N) for every nontrivial subgroup H. EXAMPLES:: sage: G = Gamma0(86) sage: G.__cmp__(G) 0 sage: G.__cmp__(GammaH(86, [11])) is not 0 True sage: Gamma1(17) < Gamma0(17) True sage: Gamma0(1) == SL2Z True sage: Gamma0(11) == GammaH(11, [2]) True sage: Gamma0(2) == Gamma1(2) True """ if not is_CongruenceSubgroup(other): return cmp(type(self), type(other)) c = cmp(self.level(), other.level()) if c: return c # Since Gamma0(N) is GammaH(N) for H all of (Z/N)^\times, # we know how to compare it to any other GammaH without having # to look at self._list_of_elements_in_H(). from all import is_GammaH, is_Gamma0 if is_GammaH(other): if is_Gamma0(other): return 0 else: H = other._list_of_elements_in_H() return cmp(len(H), arith.euler_phi(self.level())) return cmp(type(self), type(other))
def is_subgroup(self, right): """ Return True if self is a subgroup of right. EXAMPLES:: sage: G = Gamma0(20) sage: G.is_subgroup(SL2Z) True sage: G.is_subgroup(Gamma0(4)) True sage: G.is_subgroup(Gamma0(20)) True sage: G.is_subgroup(Gamma0(7)) False sage: G.is_subgroup(Gamma1(20)) False sage: G.is_subgroup(GammaH(40, [])) False sage: Gamma0(80).is_subgroup(GammaH(40, [31, 21, 17])) True sage: Gamma0(2).is_subgroup(Gamma1(2)) True """ if right.level() == 1: return True if is_Gamma0(right): return self.level() % right.level() == 0 if is_Gamma1(right): if right.level() >= 3: return False elif right.level() == 2: return self.level() == 2 # case level 1 dealt with above else: return GammaH_class.is_subgroup(self, right)